导言
面向对象(OO)语言有一个标示, 那就是他们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。前面提到过, ES 中没有类的概念, 因此它的对象也与具有类的语言中的对象不同。
理解对象
创建一个自定义对象的最简单的方式就是创建一个 Object 的实例, 然后再为它添加属性和方法
var person = new Object();
person.name = 'zs';
person.age = 23;
早期的js开发人员经常使用这个模式创建新对象,后面,对象字母量成为创建这种对象的模式。
var person = {
name : 'zs',
age : 23,
sayName : function () {
console.log(this.name)
}
}
属性类型
ES中有两种属性:数据属性和访问器属性
1.数据属性
数据属性包含一个数据值的位置。在这个位置可以读取和写入值。数据属性有4个描述行为的特性:
- Configurable : 表示能否通过 detele 删除属性从而重新定义属性 , 能否修改属性的特性, 或者能否把属性修改为访问器属性 。默认是 true
- Enumerable : 表示能否通过 for-in 循环返回属性。 默认为 true
- Writable : 表示能否修改属性的值。 默认为 true
- Value : 包含这个属性的数据值, 默认为 undefined
要修改属性默认的特性 , 必须使用 ES5 的 Object.defineProperty()方法。
var person = {};
Object.defineProperty(person, "name", {
writable : false,
value : 'zs'
})
console.log(person.name); // 'zs'
person.name = 'hw'
// 不可修改
console.log(person.name); // 'zs'
把writable 设置为 false。 这个属性的值是不可修改的,在非严格模式下,赋值操作将被忽略;在严格模型下,将报错。
var person = {};
Object.defineProperty(person , 'name', {
configurable : false,
value : 'zs'
})
console.log(person.name)
delete person.name;
console.log(person.name)
把 configurable 设置为 false , 表示不能从对象中删除属性。
一旦把属性定义为不可配置的,就不能再把它变回可配置了。此时,再调用 Object.defineProperty()方法修改除了 writable 之外的特性
在调用 Object.defineProperty()方法创建一个新的属性时,如果不指定,configurable, enumrable 和 writable 特性的默认值都是 false
2.访问器属性
访问器属性不包含数据值; 他们包含一对 getter 和 setter 函数。 访问器属性有如下4个特性:
- Configuable : 表示通过 delete 删除属性从而重新定义属性 , 能否修改属性的特性 , 或者能否把属性修改为数据属性, 特性为默认值为 true
- Enumerable : 表示能否 通过 for-in 返回循环。 默认为 true
- GET : 默认为 undefined
- SET : 默认为 undefined
定义多个属性
由于为对象定义多个属性的可能性很大 , ES5 又定义了一个 Object.defineProperties()方法。 利用这个方法可以通过描述符一次定义多个属性。 这个方法接收两个对象参数:
- 第一个对象是要添加和修改的其属性的对象
- 第二个对象的属性和第一个对象中要添加或修改的属性
读取属性的特性
使用 ES5 的 Object.getOwnPropertyDescriptor()方法, 可以获取给定属性的描述符。这个方法接收两个参数 : 属性所在的对象和要读取其描述符的属性名称
var book = {};
Object.defineProperties(person, {
_year : {
writable : true,
value : 2004
},
edition : {
writable : true,
value : 1
},
year : {
get : function() {
return this._year;
},
set : function(newValue) {
if(newValue > 2004) {
this._year = newValue;
this.edition += newValue;
}
}
}
})
var descriptor = Object.getOwnPropertyDescriptor(book, "_year");
console.log(descriptor);
//{ value: 2004, writable: true, enumerable: false, configurable: false }
创建对象
虽然 Object 构造函数或对象字母量都可以用来创建单个对象 , 但这些方式有个明显的缺点 : 使用同一个接口创建很多对象 , 会产生大量的重复代码。 为解决这个问题 , 我们可以使用工厂模式的一种变体。
工厂模式
function createPerson(name , age ,job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
console.log(this.name)
}
return o;
}
构造函数模式
ES中构造函数可用来创建特点类型的对象。 像 Object 和 Array这样。此外 , 也可以创建自定义的构造函数, 从而定义对象类型的属性和方法。例如:
function Person(name , age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
console.log(this.name)
}
}
var p1 = new Person('zs',29,'sf');
通过 new 操作符。 以这种方式调用构造函数实际上会经历以下 4 步:
function mynew(Con , ...args) {
var obj = {};
obj.__proto__ = Con.prototype;
let res = Con.apply(obj , args);
return res instanceof Object ? res : obj;
}
- 创建一个新对象
- 将构造函数的作用域赋给新对象
- 执行构造函数值的代码
- 返回新对象