现象
当我们尝试给一个字符串添加动态属性的时候,会发现不生效
1 |> let s = 'hero';
2 |> s.name = 'teemo';
3 |> console.log(s.name); // undefiend;
上面尝试给字符串s添加属性name,看似成功了,当去读取的时候却获取不到。
包装类型
上面会出现这中情况主要的原因是,js在处理字符串的读取时会做装箱操作。产生的包装对象生命周期比较特殊。比如上面的输出语句,js引擎都会做下面三个步骤
console.log(s.name); // undefined
- 创建一个 String 类型的实例
- 读取实例上的方法
- 销毁实例
可以把console.log(s.name)理解成
let s1 = new String('hero');
console.log(s1.name.toString());
上面不是已经对s.name = 'teemo'赋值操作了吗,为什么还是获取不到。原因就是第二行代码运行时会临时创建一个 String 对象,而当第三行代码执行时,这个对象已经被销毁了。第三行代码去读取字符串的时候,又创建一个新的包装对象,此时这个对象是不存在name属性。
引用类型与原始值包装类型的主要区别在于对象的生命周期。在通过 new 实例化引用类型后,得到的实例会在离开作用域时被销毁,而自动创建的原始值包装对象则只存在于访问它的那行代码执行期 间。这意味着不能在运行时给原始值添加属性和方法
给字符串添加属性
如果真的要给字符串添加属性,可以在String.prototype上定义新的属性
String.prototype.name = 'teemo';
let s = 'hero';
console.log(s.name); // teemo
不过一般场景不建议这样做,这样会影响到所有的字符串。同理Boolean、Number都具有和String一样的特点。