# 属性简洁表示法
在 ES6 之前 Object 的属性必须是 key-value 形式,如下:
let name = "xiecheng";
let age = 34;
let obj = {
name: name,
age: age,
study: function() {
console.log(this.name + "正在学习");
},
};
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
在 ES6 之后是可以用简写的形式来表达:
let name = "xiecheng";
let age = 34;
let obj = {
name,
age,
study() {
console.log(this.name + "正在学习");
},
};
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 属性名表达式
在 ES6 可以直接用变量或者表达式来定义 Object 的 key。
let s = "school";
let obj = {
foo: "bar",
[s]: "imooc",
};
1
2
3
4
5
2
3
4
5
# Object.is
判断两个对象是否相等。每次新建一个对象,相当于 new 一个 Object,两个内存地址
let obj1 = {
// new Object()
name: "xiecheng",
age: 34,
};
let obj2 = {
// new Object()
name: "xiecheng",
age: 34,
};
console.log(obj1 == obj2); // false
console.log(Object.is(obj1, obj2)); // false
let obj2 = obj1;
console.log(Object.is(obj1, obj2)); // true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# Object.assign
Object.assign(x,y) 方法用于将所有可枚举属性的值从一个或多个源对象 y 复制到目标对象 x,它将返回目标对象,相同的属性,后面覆盖前面的。
const target = {
a: 1,
b: 2,
};
const source = {
b: 4,
c: 5,
};
const returnedTarget = Object.assign(target, source);
console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
使用 in 可以判断对象中是否包含该属性
let x = {
a: 3,
b: 4,
};
console.log("a" in x);
1
2
3
4
5
2
3
4
5
# 基本语法
Object.assign(target, ...sources)
| 参数 | 含义 | 必选 |
|---|---|---|
| target | 目标对象 | Y |
| sources | 源对象 | N |
TIP
从语法上可以看出源对象的个数是不限制的(零个或多个),如果是零个直接返回目的对象,如果是多个相同属性的会被后边的源对象的属相覆盖。
let s = Object.assign({
a: 1,
});
// {a: 1}
1
2
3
4
2
3
4
注意
如果目的对象不是对象,则会自动转换为对象
let t = Object.assign(2);
// Number {2}
let s = Object.assign(2, {
a: 2,
});
// Number {2, a: 2}
1
2
3
4
5
6
2
3
4
5
6
如果对象属性具有多层嵌套,这时使用 Object.assign()合并对象会怎么样呢?
let target = {
a: {
b: {
c: 1,
},
e: 4,
f: 5,
g: 6,
},
};
let source = {
a: {
b: {
c: 1,
},
e: 2,
f: 3,
},
};
Object.assign(target, source);
console.log(target);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
我们惊奇的发现, g 属性消失了...
注意
Object.assign()对于引用数据类型属于浅拷贝。
TIP
对象的浅拷贝:浅拷贝是对象共用的一个内存地址,对象的变化相互印象。 对象的深拷贝:简单理解深拷贝是将对象放到新的内存中,两个对象的改变不会相互影响。
# 思考
- 如果目标对象传入的是 undefined 和 null 将会怎样呢?
- 如果源对象的参数是 undefined 和 null 又会怎样呢?
- 如果目标对象是个嵌套的对象,子对象的属性会被覆盖吗?
# 对象的遍历方式
如何能够遍历出对象中每个 key 和 value 的值呢?
let obj = {
name: 'xiecheng',
age: 34,
school: 'imooc'
}
Array中演示过,for...in不能够用于遍历Array,for...in的作用是用于遍历对象的。
for (let key in obj) {
console.log(key, obj[key])
}
Object.keys()用于返回对象所有key组成的数组。
Object.keys(obj).forEach(key => {
console.log(key, obj[key])
})
Object.getOwnPropertyNames()用于返回对象所有key组成的数组。
Object.getOwnPropertyNames(obj).forEach(key => {
console.log(key, obj[key])
})
Reflect.ownKeys()用于返回对象所有key组成的数组。
Reflect.ownKeys(obj).forEach(key => {
console.log(key, obj[key])
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 对象的拷贝复制
target 中的 a.g 被覆盖了
let target = {
a: {
b: {
c: 1,
},
e: 4,
f: 5,
g: 6,
},
};
let source = {
a: {
b: {
c: 1,
},
e: 2,
f: 3,
},
};
Object.assign(target, source);
console.log(target);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//基本类型是深复制,其实就是放在了单独的栈中
let a = 5;
let b = a;
a = 6;
console.log(a, b); //独立的
//引用类型放在了堆中,只是改变了栈内存中保存的地址,所以两个指向的同一个堆内存中
let obj1 = {
name: "xiecheng",
age: 34,
};
let obj2 = obj1;
obj1.age = 18;
console.log(obj1);
console.log(obj2); //也改变了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 深拷贝
方式一:使用 JSON.string
let obj1 = {
name: "xiecheng",
age: 34,
};
('{"a": "hello", "b": "world"}');
let obj = JSON.parse('{"a": "hello", "b": "world"}');
console.log(obj);
let str = JSON.stringify(obj);
console.log(str);
let str = JSON.stringify(obj1);
let obj2 = JSON.parse(str);
obj1.age = 18;
console.log(obj2);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
方式二:使用递归方式
// 检查类型
let checkType = (data) => {
//[object Array],[object object]
return Object.prototype.toString.call(data).slice(8, -1);
};
checkType({});
let deepClone = (target) => {
let targetType = checkType(target);
let result;
if (targetType === "Object") {
result = {};
} else if (targetType === "Array") {
result = [];
} else {
return target;
}
for (let i in target) {
let value = target[i];
let valueType = checkType(value);
if (valueType === "Object" || valueType === "Array") {
result[i] = deepClone(value); // 递归
} else {
result[i] = value;
}
}
return result;
};
// let arr1 = [1, 2, {age: 18}]
// let arr2 = deepClone(arr1)
// arr2[2].age = 34
// console.log(arr1)
let obj1 = {
name: "xiecheng",
hobby: ["coding", "eating"],
};
let obj2 = deepClone(obj1);
obj2.hobby[0] = "sleeping";
console.log(obj1);
console.log(obj2);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
← 函数Function 面向对象编程 →