//不考虑兼容,若考虑兼容可以使用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));
js 手撕call源码
最新推荐文章于 2023-05-25 21:57:07 发布