Skip to content

基本操作

创建对象

js
let user = new Object(); // “构造函数” 的语法
let user = {};  // “字面量” 的语法

移除属性

js
delete user.age;

添加属性

js
user["likes birds"] = true;

对带空格的多词属性要用 ["bird like"] 操作

计算属性

[] 从指定变量中获取属性名:

js
let fruit = prompt("Which fruit to buy?", "apple");

let bag = {
  [fruit]: 5, // 属性名是从 fruit 变量中得到的
};

alert( bag.apple ); // 5 如果 fruit="apple"

属性值缩写

如果对象的属性名称和当前作用域中的变量名称相同,则可以省略属性值,JavaScript 会自动将属性的值设为与属性名同名的变量的值。

js
let user = {
  name,  // 与 name:name 相同
  age: 30
};

属性存在性测试

避免存在属性但是值为 undefined 的情况。

js
let user = { name: "John", age: 30 };

alert( "age" in user ); // true,user.age 存在
alert( "blabla" in user ); // false,user.blabla 不存在。

遍历属性

js
for (key in object) {
  // 对此对象属性中的每个键执行的代码
}

属性排序

整数属性会被进行排序,其他属性则按照创建的顺序显示。

对象引用和复制

对象存储的是内存中地址(即对对象的引用),当进行复制赋值操作的时候复制的是对象的引用而非对象本身。修改任何一个对该地址的引用都可以同时修改这个对象的内容。

  • 复制引用的对象相等
  • 两个独立的空对象不相等 复制对象而指向不同的引用、合并对象
js
Object.assign(dest, [src1, src2, src3...])
  • 该方法将所有源对象的属性拷贝到目标对象 dest 中。换句话说,从第二个开始的所有参数的属性都被拷贝到第一个参数的对象中。
  • 复制过程中有同名属性则会被源对象覆盖 对象中嵌套对象的对象的复制 为了解决这个问题,并让 user 和 clone 成为两个真正独立的对象,我们应该使用一个拷贝循环来检查 user[key] 的每个值,如果它是一个对象,那么也复制它的结构。这就是所谓的“深拷贝”。 我们可以使用递归来实现它。或者为了不重复造轮子,采用现有的实现,例如 lodash 库的 _.cloneDeep(obj)

const 对象可被修改const 修饰只管对象引用地址,不管对象属性的值。只有整体修改 const 对象才会报错。

深层克隆

复制对象内的对象时使用,因为浅拷贝只复制第一层,使用 structuredClone 可以完成,或者为了兼容性使用工具库。

垃圾回收 GC

简单来说,所有不可达的资源将被释放。实现一个垃圾回收器的重点就是从 root 遍历所有的节点,未被标记的节点被回收。

this

this 的指向是在运行时计算的,比如这个例子,sayHi 的值由所属对象动态决定:

js
let user = { name: "John" };
let admin = { name: "Admin" };

function sayHi() {
  console.log(this.name);
}

// 在两个对象中使用相同的函数
user.f = sayHi;
admin.f = sayHi;

// 这两个调用有不同的 this 值
// 函数内部的 "this" 是“点符号前面”的那个对象
user.f(); // John(this == user)
admin.f(); // Admin(this == admin)

admin["f"](); // Admin(使用点符号或方括号语法来访问这个方法,都没有关系。)

箭头函数没有 this,其中的 this 指向箭头函数以外。

symbol 符号属性

“symbol” 值表示唯一的标识符, symbol 可以获得一个描述:

js
// id 是描述为 "id" 的 symbol
let id = Symbol("id");

只有字符串(其他类型会被自动转换)和 symbol 可以作为键的名称。

js
let user = {
  name: "John",
  age: 30,
  isAdmin: true,
  [Symbol("secret")]: "super secret"
}

向其他代码库中直接添加属性是不安全的,可能影响预定义行为,但是 symbol 是唯一的,第三方代码不可能知道,因此添加 symbol 类型的键名是安全的。

  • symbol 属性不参与 for..in 循环
  • 但是 Object.assign 会复制这些属性
  • Object.keys(返回所有可枚举属性)会忽略这些属性

全局 symbol

  • 可以从全局 symbol 注册表中读取、创建数据,使用 Symbol.for(key) 方法(读取、建立 symbol 数据)
  • Symbol.for(key) 可以按名字返回一个 symbol,只能返回全局的 symbol 的值,非全局会返回 undefined
  • 所有 symbol 都具有 description 属性,存储 symbol 的描述。

系统 symbol

JavaScript 内部有很多“系统” symbol,可以使用它们来微调对象的各个方面,或者改变一些内建行为。