请用 JavaScript 手写一个函数,模拟 Function.prototype.apply 的行为,要求支持指定 this 值和参数数组,并给出完整实现代码。
考察说明
考查对 JavaScript 函数调用机制、this 绑定及 apply 内部实现原理的理解与编码能力。
回答思路
- 【回答框架 1】apply 核心是改变函数执行时的 this 指向并把参数数组展开传入。实现思路:在目标对象上临时挂载该函数,通过对象方法调用触发 this 绑定,调用后删除临时属性。
- 【回答框架 2】边界处理:若第一个参数为 null 或 undefined,在非严格模式下 this 自动指向全局对象(浏览器为 window,Node 为 global),严格模式下保持 null/undefined。参数数组必须合法,否则抛 TypeError。
- 【回答框架 3】使用 Symbol 或唯一属性名避免覆盖原对象同名属性;调用后需 delete 临时属性以清理。可用 Reflect.apply 或 ES6 展开运算符对比说明。
- 【回答框架 4】代码示例:Function.prototype.myApply = function(context, args) { context = context || globalThis; const fn = Symbol('fn'); context[fn] = this; const result = context[fn](...args); delete context[fn]; return result; }。注意严格模式处理。
- 【回答框架 5】实现时需考虑函数返回值,并保证异步或生成器场景下行为一致,但核心机制相同。
- 【关键点 1】通过临时挂载属性实现 this 绑定并展开参数数组。
- 【关键点 2】null/undefined 在非严格模式下回退到全局对象,严格模式保持原值。
- 【关键点 3】用 Symbol 避免属性冲突,调用后立即删除临时属性。
- 【关键点 4】必须处理参数数组为空的场景,并返回函数原始返回值。
- 【易错点 1】忽略严格模式导致 this 绑定错误,或未处理 null/undefined。
- 【易错点 2】直接使用普通字符串属性名可能覆盖原对象方法,且忘记清理。
- 【易错点 3】未处理参数非数组导致 TypeError,或展开时依赖 ES6 语法需考虑兼容性。