为什么无法给字符串添加属性

1,931 阅读2分钟

现象

当我们尝试给一个字符串添加动态属性的时候,会发现不生效

    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一样的特点。

参考红书