对象进阶
对象字面量
let empty = {}; //没有任何属性的对象
let point = { x: 0, y: 0 }; //具有属性的对象
let book = {
//属性名中有空格,必须用字符串表示。
"main title": "JavaScript",
//属性名中有特殊字符,必须用字符串表示
"sub-title": "The Definitive Gruide",
//属性名可以是保留字,但尽量避免。
for: "all audiences",
//属性值可以是一个对象。
author: {
firstname: "David",
lastname: "Flanagan",
},
};
所有内置构造函数都具有一个继承自Object.prototype的原型。
如:Array.prototype的属性继承自Object.prototype。
通过层级的原型继承形成的链接,称为“原型链”(prototype chain)
let obj = { value: 100 };
Object.prototype.flag = "head";
console.log(obj.flag);
let arr = [1, 2, 3, 4];
console.log(arr.flag);
作为关联数组的对象
let result = {
data1: {
name: "Language",
value: "Chinese",
},
data2: {
name: "Country",
value: "China",
},
data3: {
name: "Gender",
value: "Male",
},
};
for (let i = 1; i < 4; i++) {
let data = result["data" + i];
console.log(`${data.name}-->${data.value}`);
}
属性访问错误
查询一个不存在的属性并不会报错,如果在对象o自身的属性或继承的属性中均未找到属性x,属性访问表达式o.x返回undefined。
但是,如果对象不存在,那么试图查询这个不存在的对象的属性就会报错。
let one = {};
// let one = { two: { three: 3 } };
console.log(one.two.three);
if (one) {
if (one.two) {
if (one.two.three) console.log(one.two.three);
}
}
console.log(one && one.two && one.two.three);
console.log(one?.two?.three); // Null传导运算符
枚举属性
for/in循环可以在循环体中遍历对象中所有可枚举的属性(包括自有属性和继承的属性),把属性名称赋值给循环变量。
对象继承的内置方法不可枚举的,但在代码中给对象添加的属性都是可枚举的。
let o =Object.create({m:10,n:20});
o.x=1; o.y=2; o.z=3;
for (let p in o) {
console.log(p, o[p]);
}
要想检测一个对象是否是另一个对象的原型(或处于原型链中),使用isPrototypeOf()方法。
let o = { x: 1 };
let p = Object.create(o);
p.y = 2;
console.log(Object.getPrototypeOf(p));
console.log(o.isPrototypeOf(p));
属性的特性
如果要同时修改或创建多个属性,使用Object.defineProperties()。
第一个参数是要修改的对象。
第二个参数是一个映射表,它包含要新建或修改的属性的名称,以及它们的属性描述符。
let p = Object.defineProperties(
{},
{
x: { value: 1, writable: true, enumerable: true, configurable: true },
y: { value: 1, writable: true, enumerable: true, configurable: true },
r: {
get: function () {
return Math.hypot(this.x, this.y);
},
enumerable: true,
configurable: true,
},
}
);