JavaScript 面试高频手写系列,手写对象方法,call,apply,及new关键字原理浅析实现

面试高频——常考JS对象方法原理浅析实现

1、call 方法

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

备注:该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组

Function.prototype.myCall = function(context,...args){
    // 参考call的做法,若context不存在则为winodw
    context = context || window
    //context 为传来的上下文,即要作为this的obj对象
    // this 此时为对应的方法
    // 此刻要做的就是模拟一个原方法,并将该方法的this改为context
    const fn = Symbol()  // 先创建一个symbol类型的防止命名重叠
    context[fn] = this  // 模拟原方法
    context[fn](...args)
}

2、apply方法

apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。

// 代码实现
Function.prototype.myApply = function(context,args){
    context = context || window
    const fn = Symbol()
    context[fn] = this
    context[fn](...args)
}

3、new 关键字实现

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。

new 关键字会进行如下的操作:

  1. 创建一个空的简单JavaScript对象(即{});
  2. 为步骤1新创建的对象添加属性__proto__,将该属性链接至构造函数的原型对象 ;
  3. 将步骤1新创建的对象作为this的上下文 ;
  4. 如果该函数没有返回对象,则返回this
function MyNew(fn,...args){
    // 创建一个空对象
    const obj = {}
    // 将新对象的__proto__指向它构造函数的原型
    Object.setPrototypeOf(obj,fn.prototype)
    // 调用构造函数,传参数初始化,并将this改为obj
    const result = fn.apply(obj,args)
    // 判断构造函数有没有返回值,1.返回的是基础类型,则返回实例对象,2.返回函数则返回函数,3,返回对象则返回它指定的对象
    return result instanceof Object? result:obj
}
function Person(name,age){
    this.name = name
    this.age = age
    return 22 // 实例对象
    // return function(){} // 函数
    // return {} // 指定对象
}

对象方法

1、entries

Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in 循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)。

// entries
Object.prototype.myEntries = function(obj){
    let res = []
    for(let key in obj){
        obj.hasOwnProperty(key) && res.push([key,obj[key]]) // hasOwnProperty 过略掉原型上的属性
    }
    return res
}

2、fromEntries

Object.fromEntries() 方法把键值对列表转换为一个对象。

//fromEntries
Object.prototype.myFromEntres = function(Arr){
    let obj = {}
    for(let [key,value] of Arr){
        obj[key] = value
    }
    return obj
}

3、keys

Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和正常循环遍历该对象时返回的顺序一致 。

// keys
Object.prototype.myKeys = function(obj){
    let res = []
    for(let key in obj){
        obj.hasOwnProperty(key) && res.push(key)
    }
    return res
}

4、values

Object.values()方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。

Object.prototype.myValues = function(obj){
    let res = []
    for(let key in obj){
        obj.hasOwnProperty(key) && res.push(obj[key])
    }
    return res
}

5、instanceOf

用处:A instanceOf B,判断A是否经过B的原型链

function MyInstanceOf(son,father){
    // 目标对象的原型对象
    let fp = father?.prototype
    // 自身的原型链
    let sp = son?.__proto__
    // 判断自身的原型是否在目标对象的原型链上
    while(sp){
        if(sp == fp){
            return true
        }
        // 向上找原型
        sp = sp.__proto__
    }
    // 不在原型链上返回false
    return false
}

6、is

用处:Object.is(a, b),判断a是否等于b

Object.prototype.sx_is = function (x, y) {
    if (x === y) {
        // 防止 -0 和 +0
        return x !== 0 || 1 / x === 1 / y
    }

    // 防止NaN
    return x !== x && y !== y
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值