js 手撕call原始碼
阿新 • • 發佈:2020-12-29
技術標籤:JavaScriptjavascriptcallsymbol
//不考慮相容,若考慮相容可以使用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));