1. 程式人生 > 其它 >js 手撕call原始碼

js 手撕call原始碼

技術標籤: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));