Function.prototype.call赋值给变量时异常:为何一段正常一段抛TypeError?
为什么把Function.prototype.call赋值给变量后调用会抛出TypeError?
这个问题其实戳中了JavaScript中this绑定和方法调用的核心细节,我来给你拆解清楚:
首先先明确你说的两种场景:
正常工作的代码
console.log.call(undefined, 'hello'); // 输出 "hello"
抛出异常的代码
const myCall = Function.prototype.call; myCall(console.log, 'hello'); // 抛出 TypeError: Function.prototype.call was called on incompatible [object Window](浏览器非严格模式)
核心原因:call方法的执行依赖自身的this指向
Function.prototype.call本身也是一个函数,但它的设计目的是让它的this所指向的函数,以指定的上下文执行。换句话说,call方法内部要求它自己的this必须是一个合法的函数,否则就会报错。
我们来拆解两种场景的this绑定:
- 正常场景:当你调用
console.log.call(...)时,call方法的this指向的是console.log——这是一个标准的函数,完全符合call的要求。所以call内部会正确执行console.log,传入参数'hello'。 - 报错场景:当你把
Function.prototype.call赋值给变量myCall后,调用myCall(...)时,this的绑定规则发生了变化:- 在非严格模式下,全局作用域中调用普通函数,
this默认指向全局对象(浏览器里是window,Node.js里是globalThis) - 在严格模式下,
this会是undefined
- 在非严格模式下,全局作用域中调用普通函数,
不管哪种情况,这个this都不是一个函数,而call方法内部会检查自身的this是否为函数,不符合要求就会抛出TypeError。
如何让赋值后的call正常工作?
如果非要把call赋值给变量后使用,你需要手动给它绑定正确的this(也就是你要调用的目标函数):
// 方式1:用bind绑定目标函数 const myCall = Function.prototype.call.bind(console.log); myCall(undefined, 'hello'); // 输出 "hello" // 方式2:用call的call来绑定this const myCall = Function.prototype.call; myCall.call(console.log, undefined, 'hello'); // 输出 "hello"
这两种方式都是强制让myCall(也就是call方法)的this指向console.log,从而满足它的内部要求。
总结
本质上,Function.prototype.call是一个需要依赖自身this才能工作的方法,它不是一个独立的工具函数。直接通过函数实例(比如console.log)调用call时,this会自动绑定到该函数实例;但当你把它单独抽离成变量后,this的绑定丢失,就会触发异常。
内容的提问来源于stack exchange,提问作者Eliran Pe'er
相关产品推荐
相关产品推荐

