手写 js 原生函数系列
手写 call 函数
首先介绍 call 函数:call 函数会改变 this 指向
call() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。
举个栗子:
function add(a, b) {
console.log(this, a, b);
return a + b;
};
add.call({}, 1, 2); // {} 1 2
第一版
实现 call 函数功能的基本结构,用到的知识点:
- 原型链
不足之处:
- fn 可能和 ctx 中的属性重复
Function.prototype.call2 = function(ctx, ...args) {
ctx.fn = this;
ctx.fn(...args);
delete ctx.fn;
}
function add(a, b) {
console.log(this, a, b);
return a + b;
};
add.call2({}, 1, 2); // { fn:[Function:add] } 1 2
第二版
用到的知识点:
- Symbol
- ES5 的属性描述符
不足之处:
- call 的第一个参数可能为 null 或 undefined
Function.prototype.call2 = function(ctx, ...args) {
let key = Symbol('temp');
Object.defineProperty(ctx, key, {
enumerable: false,
value: this,
});
let result = ctx[key](...args);
delete ctx[key];
return result;
}
function add(a, b) {
console.log(this, a, b);
return a + b;
};
add.call2({}, 1, 2); // {} 1 2
最后一版
Function.prototype.call2 = function(ctx, ...args) {
ctx = (ctx === null || ctx === undefined) ? globalThis : Object(ctx);
let key = Symbol('temp');
Object.defineProperty(ctx, key, {
enumerable: false,
value: this,
});
let result = ctx[key](...args);
delete ctx[key];
return result;
}
function add(a, b) {
console.log(this, a, b);
return a + b;
};
add.call2({}, 1, 2); // {} 1 2