js 手撕call源码

//不考虑兼容,若考虑兼容可以使用arguments,同时可以通过[].slice.call(arguments)将其转化为数组
Function.prototype.call = function call(context, ...params) {
     
    // this(self)->fn  context->obj  params->[10,20]
    //如果不传参或者传入null/undefined,非严格模式下为window(不考虑严格模式)
    context == null ? context = window : null;
    //如果传入的context不是对象(原始值类型无法设置属性,虽然设置了也不报错,但是访问时就是undefined)
    //new constext.constructor(context) 此方式可以创建一个对应类型的对象,但是对symbol不友好(symbol不能new)
    if (!/^(object|function)$/i.test(typeof context)) context = Object(context);
    let self = this,
        key = Symbol('KEY'),
        result;
    //symbol是唯一的,这样可以避免覆盖原对象中同名属性值
    context[key] = self;
    result = context[key](...params);
    delete context[key];
    return result;
};

function fn(x, y) {
     
    console.log(this, x, y);
    return x + y;
}
let obj = {
     
    name: 'obj',
    // call的原理 就是把context「要改变的this对象obj」和self「要执行的函数fn」之间建立关系
    // context.xxx=self;
    // context.xxx(10,20);
    // 删除新增的这个属性 delete context.xxx
    // fn: fn   //->obj.fn(10,20)
};
console.log(fn.call(100, 10, 20)); 

你可能感兴趣的:(JavaScript,javascript,call,symbol)