编写call、apply、bind的polyfill时,如何不借助三者绑定this指向?
实现思路
完全可以不依赖call/apply/bind实现this绑定,核心是利用JS原生的隐式this绑定规则:当函数作为对象的属性被调用时,函数内部的this默认指向该对象。
具体实现步骤
- 处理绑定对象的边界情况:如果传入的绑定对象是
null/undefined,默认指向全局对象;如果是字符串、数字等原始值,自动转为对应的包装对象 - 用
Symbol生成唯一的临时属性名,避免和目标对象的原有属性冲突 - 将待执行的函数赋值给目标对象的这个临时属性
- 调用目标对象上的临时方法,传入参数,此时方法内部的this会自动指向目标对象
- 执行完成后删除目标对象上的临时属性,避免污染原对象
- 返回函数执行的结果
完整代码
基础测试代码
const user = { firstName: "Christopher", lastName: "Nolan", }; const fullName = function (place, country) { console.log( `${this.firstName} ${this.lastName} is from ${place}, ${country}.` ); };
自定义_call实现
Function.prototype._call = function (...args) { const func = this; // 处理绑定对象边界情况 let ctx = args[0] ?? globalThis; ctx = Object(ctx); // 生成唯一临时属性,避免和对象原有属性冲突 const tempFnKey = Symbol('temp_exec_fn'); // 挂载函数到目标对象 ctx[tempFnKey] = func; // 截取参数并执行 const params = args.slice(1); const result = ctx[tempFnKey](...params); // 清理临时属性,不污染原对象 delete ctx[tempFnKey]; return result; };
测试效果
// 执行后输出:Christopher Nolan is from London, UK. fullName._call(user, "London", "UK");
如果需要兼容不支持
Symbol的旧环境,可以将临时属性名替换为'__temp_fn_' + Date.now() + Math.random()这类随机字符串+时间戳的组合,即可降低和原有属性重名的概率。
内容的提问来源于stack exchange,提问作者Deva
相关产品推荐
相关产品推荐

