调用严格模式与非严格模式函数时this的typeof差异
非严格模式下使用
call传入原始值时,this被包装成对象是预期行为吗?有没有解决办法? 我发现当对非严格模式的函数使用func.call(12)时,this的值是new Number(12)而不是原始值12——从代码运行结果里typeof this返回'object'就能看出来。想请教下这是JS的预期行为吗?有没有办法让非严格模式下的this也保持原始值类型?
测试代码:
function a() { return this; } function b() { 'use strict'; return this; } const x = a.call(12); console.log(typeof x); // 输出 'object' console.log(x); // 输出 Number {12} console.log(x + 3); // 输出 15 const y = b.call(12); console.log(typeof y); // 输出 'number' console.log(y); // 输出 12 console.log(y + 3); // 输出 15
这完全是预期行为,属于JavaScript非严格模式下的this绑定规则:
- 在非严格模式中,当你通过
call/apply/bind给函数传入原始值(数字、字符串、布尔值)作为this时,JS会自动执行装箱操作——把原始值包装成对应的包装对象(数字→Number对象,字符串→String对象,布尔值→Boolean对象)。这是早期JS设计的历史遗留行为,目的是让原始值能调用原型上的方法(比如12.toString())。 - 而严格模式则取消了这个自动装箱行为,传入的原始值会直接作为
this的值,不会被包装成对象,这也是严格模式更符合直觉的原因之一。
解决办法
如果你需要在非严格模式下让this保持原始值类型,有两种常用方式:
手动将
this转换为原始值
在函数内部,你可以通过valueOf()方法或者一元+运算符把包装对象转回原始值:function a() { // 两种方式任选其一 return this.valueOf(); // 或者 return +this; } const x = a.call(12); console.log(typeof x); // 输出 'number' console.log(x); // 输出 12开启严格模式
这是更推荐的方案,直接在函数内部或者整个脚本顶部添加'use strict';声明,这样call传入的原始值就不会被自动装箱了,和你代码里的函数b表现一致。严格模式不仅能解决这个问题,还能避免很多JS的怪异行为,提升代码的安全性和性能。
内容的提问来源于stack exchange,提问作者Jessy
相关产品推荐
相关产品推荐

