对象
let user = {
name: "John",
age: 30,
"likes birds": true // 多词属性名必须加引号,
};
//----------------
let user = {
name: "John",
age: 30
};
let key = prompt("What do you want to know about the user?", "name");
// 获取变量
alert( user[key] ); // John (如果输入 "name" )
变量名不能用保留字段,像:“for”, “let”, “return” 等。
对于对象的属性,没有这些限制,都可以的:
let obj = {
for: 1,
let: 2,
return: 3
}
alert( obj.for + obj.let + obj.return ); // 6
基本上,什么都可以,只有一个特殊的:"__proto__" 因为历史原因要特别对待。比如,我们不能把它设置为非对象的值:
如果我们蓄意去存储随机的键值对或者允许一个访问者去指定键,那可能就会产生很多 bug 并且使对象变得危险。
比如,访问者可能选择 “proto” 作为键,这个赋值的逻辑就失败了(像上面那样)。
2.存在值检查
对象的一个显著的特点就是可以访问任何属性,如果这个属性名没有值也不会有错误。访问一个不存在的属性会返回undefined。它提供一种普遍的方法去检查属性是否存在 —— 获得值来与 undefined 比较:
同样也有一个特别的操作符 "in" 来检查是否属性存在。
语法是:
"key" in object
//----------------------------------------
let user = { name: "John", age: 30 };
alert( "age" in user ); // true,user.age 存在
alert( "blabla" in user ); // false,user.blabla 不存在。
//-------------------------------------
let user = { age: 30 };
let key = "age";
alert( key in user ); // true,获取键的名字和检查这个键的属性
3.“for…in” 循环
for(key in object) {
// 各个属性键值的执行区
}
例如,我们列出 user 所有的属性值:
let user = {
name: "John",
age: 30,
isAdmin: true
};
for(let key in user) {
// keys
alert( key ); // name, age, isAdmin
// 属性键的值
alert( user[key] ); // John, 30, true
}
4.像对象一样排序
5.引用复制
6.对象都是按引用存储复制的。
变量存储的不是对象本身,而是对象的“内存地址”,是对象的引用。
当对象被复制的时候 – 引用被复制了一份, 对象并没有被复制。
7.常量对象
一个被 const 修饰的对象可以被修改。
8.复制和合并,Object.assign
复制一个对象的变量也等同于创建了此对象的另一个引用。
那么我们该怎么复制一个对象呢?创建一份独立的拷贝,一份复制?
这也是可行的,但是有一点麻烦,因为JS并没有原生的方法支持这么做。实际上,我们很少这么做。复制引用很多时候是好用的。
如果我们真的想这么做,就需要创建一个新的对象,遍历现有对象的属性,在原始值的状态下复制给新的对象。
像这样:
let user = {
name: "John",
age: 30
};
let clone = {}; // 新的空对象
// 复制所有的属性值
for (let key in user) {
clone[key] = user[key];
}
// 现在复制是独立的复制了
clone.name = "Pete"; // 改变它的值
alert( user.name ); // 原对象属性值不变
我们也可以用Object.assign 来实现。
语法是:
Object.assign(dest[, src1, src2, src3...])
例如,我们可以用这个方法来把几个对象合并成一个:
let user = { name: "John" };
let permissions1 = { canView: true };
let permissions2 = { canEdit: true };
// 把 permissions1 和 permissions2 的所有属性都拷贝给 user
Object.assign(user, permissions1, permissions2);
// 现在 user = { name: "John", canView: true, canEdit: true }
如果接收的对象(user)已经有了同样属性名的属性,前面的会被覆盖:
let user = { name: "John" };
// 覆盖 name,增加 isAdmin
Object.assign(user, { name: "Pete", isAdmin: true });
// 现在 user = { name: "Pete", isAdmin: true }
它复制了 user 对象所有的属性给了一个空对象,然后返回拷贝后的对象。事实上,这跟循环赋值一样,但是更短。
let user = {
name: "John",
age: 30
};
let clone = Object.assign({}, user)
如果对象属性指向对象
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
alert( user.sizes.height ); // 182
//现在,并不能拷贝 clone.sizes = user.sizes,因为 user.sizes 是一个对象,它按引用拷贝。所以 clone 和 user 共享了一个对象。
let user = {
name: "John",
sizes: {
height: 182,
width: 50
}
};
let clone = Object.assign({}, user);
alert( user.sizes === clone.sizes ); // true,同一个对象
// user 和 clone 共享 sizes 对象
user.sizes.width++; // 在这里改变一个属性的值
alert(clone.sizes.width); // 51,在这里查看属性的值
总结
对象是具有一些特殊特性的关联数组。
他们存储键值对:
- 属性的键必须是字符串或者符号(通常是字符串)。
- 值可以是任何类型。
我们可以用下面的方法获取属性:
- 点符号:
obj.property。 - 方括号
obj["property"],方括号中可以使用变量obj[varWithKey]。
其他操作:
- 删除属性:
delete obj.prop。 - 检查属性是否存在:
"key" in obj。 - 遍历对象:
for(let key in obj)循环。
对象根据引用来赋值或者复制。换句话说,变量存的不是对象的"值",而是值的 “引用”(内存地址)。 所以复制变量或者传递变量到方法中只是复制了对象的引用。 所有的引用操作(像增加,删除属性)都作用于同一个对象。
深拷贝的话我们可以使用 Object.assign 或者 _.cloneDeep(obj)。

浙公网安备 33010602011771号