call是函数对象的原生方法,用于临时指定并立即执行函数时的this值,第一个参数为thisArg,后续参数依次传入目标函数,不修改原函数。

call 是什么,为什么能改 this
call 是函数对象上的原生方法,它不修改原函数,而是「临时指定」执行时的 this 值,并立即调用。关键点在于:它只影响当次执行,且必须显式传入第一个参数作为新 this(哪怕传 null 或 undefined,非严格模式下也会被转成全局对象)。
常见误判是以为 call 会“绑定”函数——其实那是 bind 干的事。而 call 就是“现在就用这个 this 跑一次”。
call 的参数怎么传:第一个是 this,后面全是实参
call 的签名是 func.call(thisArg, arg1, arg2, ...)。第一个参数决定函数体内 this 指向;从第二个开始,每个参数都按顺序传给目标函数。
- 如果目标函数接收 2 个参数,但你只传了 1 个实参,那第 2 个形参就是
undefined - 不能把多个参数塞进一个数组里直接传——那整个数组会变成第一个实参;要用
apply或展开运算符(但call本身不支持展开) - 想传数组当参数列表?得手动解构:
func.call(obj, ...arr)(ES6+),或退化用apply
示例:
function greet(greeting, punctuation) {
return `${greeting}, ${this.name}${punctuation}`;
}
const person = { name: 'Alice' };
greet.call(person, 'Hello', '!'); // "Hello, Alice!"
容易踩的坑:null/undefined、箭头函数、call 后没括号
三个高频翻车点:
- 传
null或undefined作thisArg:非严格模式下,this会变成全局对象(浏览器里是window),可能意外污染全局变量 - 对箭头函数调用
call:无效。箭头函数的this是词法绑定的,无法被call/apply/bind修改 - 写成
func.call(obj, arg)却忘了它本身已是调用动作——后面**不能再加括号**,即不能写成func.call(obj, arg)(),否则报TypeError: func.call(...) is not a function
替代方案对比:call vs apply vs bind
三者用途不同,别混用:
-
call:适合参数数量固定、明确知道要传哪几个值的场景 -
apply:适合参数以数组形式存在,比如Math.max.apply(null, arr) -
bind:返回一个新函数,this和部分参数被预设好,不立即执行
性能上无显著差异,选哪个纯看参数形态和是否需要延迟执行。但注意:bind 返回的函数再调用 call,是可以覆盖掉预设的 this 的——除非用 bind 两次(第一次绑 this,第二次绑参数),那就真锁死了。
真正容易被忽略的是:call 不会改变原函数的原型链、length 属性或 name,它只是“借个 this 跑一趟”。如果你在代理函数或封装逻辑里反复用 call,记得检查 this 绑定是否真的符合预期,而不是靠调试器里看到的“当前 this”来判断——因为那个可能是外层作用域的 this。










