原始类型包装器在严格模式下this指向原始值而非包装对象,导致属性赋值静默失败;方法调用仍自动装箱,但call/apply传入原始值时this保持原始类型。

原始类型包装器(如 String、Number、Boolean)在严格模式下会影响 this 的指向,关键在于:**它们不是“构造函数调用”,而是隐式装箱行为;而严格模式会禁止非对象上下文中的 this 自动绑定为全局对象**。
为什么原始值能调用方法?——装箱机制
原始值本身没有属性和方法,但 JS 引擎会在调用其方法时临时创建对应的包装对象(即“装箱”):
-
"hello".toUpperCase()→ 引擎临时生成new String("hello"),在其上调用toUpperCase -
(123).toFixed(2)→ 临时生成new Number(123) - 这个临时对象只在本次方法调用中存在,调用结束即被销毁
严格模式下 this 指向 undefined 而非全局对象
包装器的原型方法(如 String.prototype.charAt)内部若使用 this,其值取决于调用方式:
- 非严格模式:
"abc".charAt(0)中,this指向临时String对象(正常) - 严格模式下,如果手动用
call/apply绑定原始值,this就是那个原始值本身 —— 但原始值不是对象,所以this会被设为undefined
例如:
'use strict';
String.prototype.inspect = function() {
return typeof this; // 'object'(装箱后)→ 正常
};
"test".inspect(); // 'object'
// 但手动 call 原始值:
String.prototype.inspect.call("test"); // 'object'(仍装箱)
String.prototype.inspect.call(42); // 'number'(数字原始值 → this 是 42)
String.prototype.inspect.call(null); // 'object'(null 被转为 globalThis,但严格模式下为 undefined?注意:null/undefined 在 call 中会被转为 globalThis,但严格模式下不会自动转!)
重点来了:在严格模式中,Function.prototype.call 和 apply 对原始值参数的处理是——不强制转为对象。所以:
-
func.call("str")→this就是字符串"str"(原始值) - 若该函数体里写了
this.xxx = 1,会静默失败(原始值不可写属性),且this不再是包装对象
常见陷阱:自定义方法中误用 this
如果你给 String.prototype 添加一个方法,并在其中依赖 this 是对象,那在严格模式下传入原始字符串可能出问题:
'use strict';
String.prototype.logLength = function() {
console.log(this.length); // ✅ 正常:装箱后 this 是 String 实例
};
String.prototype.badLog = function() {
this.custom = 'x'; // ❌ 静默失败:this 是原始字符串,不能添加属性
console.log(this.custom); // undefined
};
"hi".logLength(); // 2
"hi".badLog(); // undefined
此时 this 确实是装箱后的对象,但严格模式下对原始值的赋值操作不会触发自动装箱来支持写入 —— 实际上,引擎会先尝试将 this 转为对象(即装箱),但赋值操作仍无效,因为返回的是新包装对象,原调用上下文未保留。
总结:核心差异一句话
严格模式不改变“方法调用时自动装箱”的行为,但会让 this 更真实地反映调用时的接收者:如果是原始值直接参与 call,this 就是那个原始值;而方法体内对 this 的属性操作,在原始值上一律无效,且不会抛错(静默失败),这和非严格模式下可能悄悄转成包装对象并允许写入不同。

















