基本操作
创建对象:
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,可以使用它们来微调对象的各个方面,或者改变一些内建行为。