1.理解对象
在ECMA-262中将对象定义为一组无序组合。对象的每个属性或方法都由一个名称来标识,这个名称映射到一个值,值可以是数据或者函数。创建自定义对象就是使用**Object()**函数
let person = new Object();
person.name = 'meta';
person.age = 23;
person.sayName = function () {
console.log(this.name);
}
也可以使用对象字面量来创建对象
let person = {
name = 'meta',
age = 23,
sayName = function () {
console.log(this.name)
}
};
对象属性的类型
数据属性
/*Configurable : 属性是否可用delete删除并重新定义,是否可修改特性,是否可改为访问器属性
Enumerable : 属性是否可用for-in循环返回
Weitable : 属性是否可被修改
Value : 属性的值*/
let person = {};
Object.defineProperty(person, "name", {
configurable: true,
enumerable: false,
writable: true,
value: 'meta'
});
console.log(person.name)
//meta
访问器属性
/*Configurable:属性是否可用delete删除并重新定义,是否可修改特性,是否可改为访问器属性
Enumerable:属性是否可用for-in循环返回
Get:获取函数,在读取属性时调用
Set:设置函数,在写入属性时调用*/
let person = {
id_: '10001'
};
Object.defineProperty(person, "id", {
configurable: true,
enumerable: false,
get() {
return this.id_;
},
set(name) {
this.id_ = name;
}
});
console.log(person.id);
person.id = '10002';
console.log(person.id);
//_常用来表示该属性并不希望在对象方法的外部被访问到
同时定义多个属性
let person = {};
Object.defineProperties(person, {
id_: {
value: '10001'
},
name: {
value: 'meta'
},
id: {
get() {
return this.id_
},
set(id) {
this.id_ = id
}
}
});
console.log(person.id, person.name)
//10001 meta
获取属性特性
let person = {};
Object.defineProperty(person, "name", {
configurable: true,
enumerable: false,
writable: true,
value: 'meta'
});
let descriptor = Object.getOwnPropertyDescriptor(person, "name");
console.log(descriptor);
/*
{
value: 'meta',
writable: true,
enumerable: false,
configurable: true
}
*/
对象解构
let person = {
name: 'meta',
id: '10001'
};
let { name, id } = person;
let { name: personName, id: personId } = person;
console.log(name, id, personName, personId);
//meta 10001 meta 10001
2.创建对象
虽然使用**Object()**构造函数或字面量可以方便的创建对象,但是这些方式也有明显的不足:创建具有相同接口的多个对象需要重复编写很多代码。
工厂模式
function createPerson(name, id) {
let o = new Object();
o.name = name;
o.id = id;
o.sayName = function () {
console.log(this.name);
}
return o;
}
let p1 = createPerson('meta1', '10001');
let p2 = createPerson('meta2', '10002');
console.log(p1, p2);
//{ name: 'meta1', id: '10001', sayName: [Function (anonymous)] } { name: 'meta2', id: '10002', sayName: [Function (anonymous)] }
构造函数模式
function Person(name, id) {
this.name = name;
this.id = id;
this.sayName = function () {
console.log(this.name);
}
}
let p1 = new Person('meta1', '10001');
let p2 = new Person('meta2', '10002');
console.log(p1, p2);
//Person { name: 'meta1', id: '10001', sayName: [Function (anonymous)] } Person { name: 'meta2', id: '10002', sayName: [Function (anonymous)] }
原型模式
function Person() { };
Person.prototype.name = 'meta';
Person.prototype.id = '10001';
Person.prototype.sayName = function () {
console.log(this.name);
};
let p1 = new Person();
let p2 = new Person();
p1.sayName();
p2.sayName();
//meta
//meta
3.继承
组合继承
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function () {
console.log(this.name);
};
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function () {
console.log(this.age);
};
let instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
console.log(instance1.colors); // "red,blue,green,black"
instance1.sayName(); // "Nicholas";
instance1.sayAge(); // 29
let instance2 = new SubType("Greg", 27);
console.log(instance2.colors); // "red,blue,green"
instance2.sayName(); // "Greg";
instance2.sayAge(); // 27
原型式继承
function object(o) {
function F() { }
F.prototype = o;
return new F();
}
let person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
let anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
let yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
console.log(person.friends); // "Shelby,Court,Van,Rob,Barbie"
寄生式继承
function object(o) {
function F() { }
F.prototype = o;
return new F();
};
function createAnother(original) {
let clone = object(original);
clone.sayHi = function () {
console.log('hi');
}
return clone;
};
let person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
let anotherPerson = createAnother(person);
anotherPerson.sayHi() //hi
寄生式组合继承
function SuperType(name) {
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function() {
console.log(this.name);
};
function SubType(name, age){
SuperType.call(this, name); // second call to SuperType()
this.age = age;
}
SubType.prototype = new SuperType(); // first call to SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
console.log(this.age);
};
4.类
在ES6中引入了class关键字具有正式定义类的能力。
类定义
// class declaration
class Person {}
// class expression
const Animal = class {};
类构造函数
class Animal {}
class Person {
constructor() {
console.log('person ctor');
}
}
class Vegetable {
constructor() {
this.color = 'orange';
}
}
let a = new Animal();
let p = new Person(); // person ctor
let v = new Vegetable();
console.log(v.color); // orange
继承
class Vehicle {}
// Inherit from class
class Bus extends Vehicle {}
let b = new Bus();
console.log(b instanceof Bus); // true
console.log(b instanceof Vehicle); // true
function Person() {}
// Inherit from function constructor
class Engineer extends Person {}
let e = new Engineer();
console.log(e instanceof Engineer); // true
console.log(e instanceof Person); // true
ClassInheritanceExample01.js