JavaScript中call()的显式绑定机制及传null时的this指向疑问
JavaScript call() 显式绑定的核心工作原理
call() 是挂在Function原型上的内置方法,作用是在函数执行时手动指定本次调用的this指向,优先级高于隐式绑定、默认绑定的触发规则:
- 调用格式为
函数.call(要绑定的this值, 入参1, 入参2...),调用后会立刻执行当前函数,将传入的第一个参数作为函数运行时的上下文this - 这种主动手动指定this的调用方式,就是显式绑定,和其他由调用位置自动推导this的规则相互独立
传入null/不传参调用call()的绑定类型判定
- 该场景不属于隐式绑定:隐式绑定的核心触发逻辑是函数作为对象的成员属性被调用,this由对象属性访问的上下文自动推导;而call()本身是主动手动指定this的调用路径,哪怕传入null,本质还是走显式绑定的逻辑分支,和隐式绑定的触发机制完全独立。
- 空入参的兼容规则:
- 非严格模式下:如果call()传入的this值是null/undefined,引擎会自动把本次函数执行的this替换为全局对象(浏览器环境为window,Node环境为globalThis)
- 严格模式下:如果call()传入的this值是null/undefined,this会保持传入的原始值,不会自动替换为全局对象
示例代码输出异常的原因分析
涉及的示例代码如下:
function foo() { console.log( this.a ); } var a = 2; foo.call( null );
不同环境下的输出差异
- 代码注释中标注的预期输出2,成立的前提是:代码运行在非严格模式、全局脚本(非模块)环境中。该场景下
var a = 2会作为可枚举属性挂载到全局对象上,foo.call(null)会把this自动绑定到全局对象,此时this.a等价于全局对象上的a属性,值为2。 - 实际运行得到undefined的核心触发原因,是运行环境不符合上述全局脚本的前提,常见场景包括:
- 代码运行在ES Module、CommonJS模块、前端打包工具的模块作用域中:顶层声明的
var a = 2属于模块内部的作用域变量,不会挂载到全局对象的属性上。此时哪怕call(null)在非严格模式下把this绑定到全局对象,全局对象上也不存在a这个属性,访问结果自然为undefined。 - 代码运行在严格模式下:call(null)不会自动把this指向全局,此时this本身就是null,直接访问this.a会抛出类型错误;若代码被转译逻辑规避了运行错误,访问结果也会返回undefined。
- 代码运行在ES Module、CommonJS模块、前端打包工具的模块作用域中:顶层声明的
实际开发中如果没有特殊的this绑定需求,不建议给call()传入null作为this值,很容易触发环境兼容问题,更稳妥的占位方案是传入一个空对象作为临时this值。
内容的提问来源于stack exchange,提问作者Sarthak Gupta
相关产品推荐
相关产品推荐

