likes
comments
collection
share

"深入探索JavaScript核心:解密对象、'new'操作符与包装类的奥秘"

作者站长头像
站长
· 阅读数 59

在JavaScript中,对象是核心的数据结构之一,它们允许我们将数据和功能组织在一起。理解对象的工作原理,包括其创建方式、new操作符的作用,以及包装类的概念,对于深入学习JavaScript至关重要。

对象基础

首先,让我们明确对象中的键(key)确实主要是字符串类型。虽然ES6引入了Symbol作为另一种键的类型,但字符串仍然是最常见和基础的。对象可以存储键值对,其中键用于访问与之关联的值。

创建对象的三种方式

  1. 对象字面量:这是创建单个对象最直接的方式。

    const obj = { key: 'value' };
    
  2. new Object()构造函数:通过调用内置的Object构造函数来创建一个新对象。

    const obj = new Object();
    obj.key = 'value';
    
  3. 自定义构造函数:使用new关键字配合自定义的构造函数来创建特定类型的对象。

    function Person(name) {
      this.name = name;
    }
    const person = new Person('Tang');
    

new操作符的魔法

当使用new操作符调用一个构造函数时,JavaScript会执行以下步骤:

  1. 创建一个新的空对象new操作符首先会在内存中创建一个空的对象,并将其作为this上下文。

  2. 执行构造函数中的代码:接着,构造函数的代码会被执行。在这一步,可以通过this关键字给新创建的对象添加属性和方法,如this.property = value;

  3. 返回this对象:构造函数执行完毕后,如果未显式返回其他对象,new操作符会自动返回这个被构造函数修改过的this对象。这意味着你得到的是一个拥有指定属性和方法的新实例。

包装类的奥秘

原始值(如数字、字符串、布尔值)在JavaScript中被视为基本数据类型,它们不是对象,因此理论上不应有属性和方法。然而,为了方便操作,JavaScript提供了包装对象(或称为包装类):NumberStringBoolean。这些包装对象允许原始值临时具备对象特性。

当你尝试给原始值添加属性或调用方法时(如"text".toUpperCase()),JavaScript引擎实际上执行了以下操作:

  1. 创建包装对象:引擎会为该原始值创建一个对应的包装对象(如String对象)。
  2. 执行操作:在这个包装对象上执行所需的操作(如调用方法)。
  3. 销毁包装对象:操作完成后,如果该操作没有导致包装对象被引用(比如赋值给某个变量),那么这个包装对象会被销毁,以保持原始值的轻量级特性。这就是所谓的“临时封装”,确保原始值的本质不变,依旧遵循不具有属性和方法的规则。

下面示例展示了JavaScript中数组和字符串在处理长度属性时的行为,这里我们详细解析一下每个部分:

数组示例

var arr=[1,2,3,4,5];
arr.length = 2;
console.log(arr); //[ 1, 2 ]

数组arr的初始长度为5。当我们设置arr.length = 2时,JavaScript会改变数组的长度属性,同时自动删除索引大于或等于新长度的元素。因此,数组arr被截断,仅保留前两个元素12

字符串示例

var str ='abcde';
console.log(str.length); //5
str.length=2;
console.log(str); //'abcde'

对于字符串str,情况有所不同。尽管您尝试通过str.length = 2来修改字符串的长度,但实际上字符串的长度是不可变的。字符串在JavaScript中被视为原始值,理论上不应有可修改的属性。

当您尝试修改str.length时,实际上发生的是:

  1. 临时转换:为了能够访问.length属性,JavaScript会将原始字符串值包装成一个临时的String对象。
  2. 尝试修改:然后您尝试设置这个临时对象的length属性为2。但是,由于字符串是不可变的,修改length属性并不会影响原始字符串的内容。
  3. 属性无效:正如您指出的,原始值不能拥有属性和方法,因此这个对length的修改尝试实际上是无效的,并且不会影响到原始的字符串str
  4. 临时对象销毁:一旦属性访问或方法调用完成,这个临时的String对象就会被销毁,所以任何对它的修改都不会持久化。

因此,尽管您执行了str.length = 2,输出str时,它仍然保持为'abcde',长度为5,因为字符串的长度是不可更改的。实际上,并没有执行类似delete str.length的操作;尝试修改只是没有效果而已,因为字符串的不可变性保护了其长度属性不被外部修改。

值得注意的是,V8引擎(Chrome、Node.js等使用的JavaScript引擎)在设计上会对这种临时创建的包装对象进行优化,确保它们不会意外地保留额外的属性,从而保持了原始值的纯净性。

总结

总之,对象、new操作符以及包装类是JavaScript中处理数据和实现面向对象编程的重要概念。掌握它们的工作原理,能帮助开发者更有效地利用JavaScript的强大功能。

转载自:https://juejin.cn/post/7376441410357166091
评论
请登录