面向对象编程 -- 理解对象1
// 创建自定义对象的通常方式是创建 Object 的一个新实例,然后再给它添加属性和方法。
let person = new Object();
person.name = "Nicholas";
person.age = 29;
person.job = "Software Engineer";
person.sayName = function() {
console.log(this.name);
};
// 前面的例子如果使用对象字面量则可以这样写:
let person = {
name: "Nicholas",
age: 29,
job: "Software Engineer",
sayName() {
console.log(this.name);
}
};
一、属性的类型
// ECMA-262 使用一些内部特性来描述属性的特征。
// 为了将某个特性标识为内部特性,规范会用两个中括号把特性的名称括起来,比如[[Enumerable]]。
// 属性分两种:数据属性和访问器属性。
1.数据属性
// 数据属性包含一个保存数据值的位置。
// 数据属性有4个特性描述他们的行为。
1.[[Configurable]]:表示属性是否可以通过 delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。
2.[[Enumberable]]:表示属性是否可以通过 for-in 循环返回。
3.[[writable]]:表示属性的值是否可以被修改。
4.[[Value]]:包含属性实际的值。
let person = {};
Object.defineProperty(person, "name", {
writable: false,
value: "Nicholas"
});
console.log(person.name); // "Nicholas"!
person.name = "Greg";
console.log(person.name); // "Nicholas"
// 类似的规则也适用于创建不可配置的属性。
let person = {};
Object.defineProperty(person, "name", {
configurable: false,
value: "Nicholas"
});
console.log(person.name); // "Nicholas"
delete person.name;
console.log(person.name); // "Nicholas"
// 一个属性被定义为不可配置之后,就不能再变回可配置的了。
let person = {};
Object.defineProperty(person, "name", {
configurable: false,
value: "Nicholas"
});
// Throws an error
Object.defineProperty(person, "name", {
configurable: true,
value: "Nicholas"
});
2.访问器属性
// 访问器属性不包含数据值。
// 访问器属性有4个特性描述他们的行为。
1.[[Configurable]]:表示属性是否可以通过 delete 删除并重新定义,是否可以修改它的特性,以及是否可以把它改为访问器属性。
2.[[Enumberable]]:表示属性是否可以通过 for-in 循环返回。
3.[[Get]]: 获取函数,在读取属性时调用。
4.[[Set]]: 设置函数,在写入属性时调用。
let book = {
year_: 2017,
edition: 1
};
Object.defineProperty(book, "year", {
get() {
return this.year_;
},
set(newValue) {
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
});
book.year = 2018;
console.log(book.edition); // 2
二、定义多个属性
// 在一个对象上同时定义多个属性的可能性是非常大的。
let book = {};
Object.defineProperties(book, {
year_: {
writable:true,
value: 2017
},
edition: {
writable:true,
value: 1
},
year: {
get() {
return this.year_;
},
set(newValue) {
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
},
});
三、读取属性的特性
// 使用 Object.getOwnPropertyDescriptor() 方法可以取得指定属性的属性描述符。
let book = {};
Object.defineProperties(book, {
year_: {
writable:true,
value: 2017
},
edition: {
writable:true,
value: 1
},
year: {
get() {
return this.year_;
},
set(newValue) {
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
},
});
let descriptor = Object.getOwnPropertyDescriptor(book, "year_");
console.log(descriptor.value); // 2017
console.log(descriptor.configurable); // false
console.log(typeof descriptor.get); // undefined
let descriptor2 = Object.getOwnPropertyDescriptor(book, "year");
console.log(descriptor2.value); // undefined
console.log(descriptor2.configurable); // false
console.log(typeof descriptor2.get); // function
// ECMAScript 2017 新增了 Object.getOwnPropertyDescriptors()静态方法。
let book = {};
Object.defineProperties(book, {
year_: {
writable:true,
value: 2017
},
edition: {
writable:true,
value: 1
},
year: {
get() {
return this.year_;
},
set(newValue) {
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
},
});
console.log(Object.getOwnPropertyDescriptors(book));
博文查考
JavaScript 高级程序设计(第4版) --【美】马特.弗里斯比 著