Appearance
实现一个 apply 方法
在 Function.prototype
上有一个 apply()
方法,可以改变函数运行时 this
的值。
Code
javascript
/**
* apply 实现
* @param {object} context
* @returns {any}
*/
Function.prototype.myApply = function (context) {
const ctx = context ? Object(context) : globalThis;
// 借助 Symbol 创建一个唯一的 key
const key = Symbol('fn');
// 将函数挂载到对象上
ctx[key] = this;
let result;
// 无参调用无法使用展开运算符,因此需要进行判断
if (arguments[1]) {
result = ctx[key](...arguments[1]);
} else {
result = ctx[key]();
}
// symbol 属性无法通过 delete 进行删除,因此使用 Reflect
Reflect.deleteProperty(ctx, key);
// 返回函数运行结果
return result;
};
Test Cases
javascript
require('./apply');
function logAge() {
return this.age;
}
function getAgeWithArgs(...nums) {
return this.age + nums.reduce((acc, cur) => acc + cur, 0);
}
const obj = {
age: 18,
};
describe('test apply', () => {
it('should be undefined', () => {
expect(logAge()).toBe(undefined);
});
it('should be 18', () => {
expect(logAge.myApply(obj)).toBe(18);
});
it('should be 24', () => {
// has arguments
expect(getAgeWithArgs.myApply(obj, [1, 2, 3])).toBe(24);
});
it('should be 18', () => {
// no arguments
expect(getAgeWithArgs.myApply(obj)).toBe(18);
});
});