创建对象的方法
1.字面量
// 优点:简单方便
// 缺点:每创建一个对象都要重新写,且创建多个比较占内存
var obj1 = {
name: 'liuhui1'
};
var obj2 = new Object({
name: 'liuhui2'
});
var obj3 = Object.create({
name: 'liuhui3'
});
2.工厂模式
// 优点:改善了字面量方法创建多个相似对象的问题,不需要编写重复的代码
// 缺点:没有解决对象是别的问题,不知道对象的类型是什么
function person () {
var obj = new Object();
obj.name = 'liuhui4';
obj.sayName = function () {
console.log(this.name);
};
return obj;
}
var obj4 = person();
console.log(obj4.sayName());
3.构造函数模式
// 优点:创建并定义了对象类型的属性和方法,可以标示为特定的类型(自定义构造函数,原生:Object/Array)
// 缺点:方法没有被共享,每次实例一个对象都要重复绑定一个独立的方法
function Person (name) {
this.name = name;
this.sayName = function () {
console.log(this.name);
};
this.newFun = newFun;
}
// 解决办法:将方法写在全局,但是就变成全局方法了跟封装的观念相违背了
// 新增代码
function newFun () {
console.log('new name: ' + this.name);
}
var obj5 = new Person('liuhui5');
console.log(obj5.sayName());
4.原型模式
// 优点:将方法封装到相应的原型对象上,私有并实例可以共享这些属性和方法
// 缺点:所有属性和方法都共享了,改变实例的属性和方法会影响原型对象上的属性和方法
function Person1 () {
}
Person1.prototype = {
constructor: Person1,
name: 'liuhui6',
sayName: function () {
console.log(this.name);
}
};
var obj6 = new Person1();
console.log(obj6.sayName());
5.组合模式(构造函数+原型模式)还没有完全理解
// 优点:构造函数用于定义实例属性和方法,原型模式用于共享定义的属性和方法
function Person2 (name) {
this.newName = function () {
console.log(name);
}
}
Person2.prototype = {
constructor: Person2,
name: 'liuhui7',
sayName: function () {
console.log(this.name);
}
};
var obj7 = new Person2();
var obj8 = new Person2('liuhui8');
继承的方法
1.借助构造函数实现继承
// 缺点:父级构造函数属性和方法没有被共享
function Parent1 () {
this.name = 'parent1';
this.play = [1, 2, 3];
}
function Child1 () {
Parent1.call(this); // 关键:执行父级构造函数,深复制
this.type = 'child1';
}
Parent1.prototype.say = function () {
console.log('hello1');
};
console.log(new Child1());
var s1 = new Child1();
var s2 = new Child1();
s1.play.push(4);
console.log(s1.play, s2.play, s1.hasOwnProperty('play'), 'test1');
2.借助原型链实现继承
// 缺点:原型链上的属性和方法是共享
function Parent2 () {
this.name = 'parent2';
this.play = [1, 2, 3];
}
function Child2 () {
this.type = 'child';
}
Parent2.prototype.say = function () {
console.log('hello2');
};
Child2.prototype = new Parent2(); // 关键:将子级执行父级构造函数实现继承,浅复制
console.log(new Child2(), new Child2().say());
var s3 = new Child2();
var s4 = new Child2();
s3.play.push(4);
console.log(s3.play, s4.play, s3.hasOwnProperty('play'), 'test2');
3.组合方式
// 缺点:父级构造函数执行了两遍
function Parent3 () {
this.name = 'parent3';
this.play = [1, 2, 3];
}
function Child3 () {
Parent3.call(this); // 关键1
this.type = 'child3';
}
Parent3.prototype.say = function () {
console.log('hello3');
};
Child3.prototype = new Parent3(); // 关键2
var s5 = new Child3();
var s6 = new Child3();
s5.play.push(4);
console.log(s5, s6, s5.hasOwnProperty('play'), 'test');
4.组合方式优化1
// 缺点:实例属性constructor指向父级构造函数,使用instanceof不能正确判断对象类型
function Parent4 () {
this.name = 'parent4';
this.play = [1, 2, 3];
}
function Child4 () {
Parent4.call(this);
this.type = 'child4';
}
Parent4.prototype.say = function () {
console.log('hello4');
};
Child4.prototype = Parent4.prototype;
Child4.prototype.constructor = Child4; // 新增代码,让实例指向其真实的构造函数
var s7 = new Child4();
var s8 = new Child4();
s7.play.push(4);
console.log(s7, s8);
// 判断是子原型Child4实例化还是Parent4直接实例化的
console.log(s7 instanceof Child4, s8 instanceof Parent4); // 判断不了
console.log(s7.constructor, s8.constructor, s7.hasOwnProperty('play'), 'test');
5.组合方式优化2
function Parent5 () {
this.name = 'parent5';
this.play = [1, 2, 3];
}
function Child5 () {
Parent5.call(this);
this.type = 'child5';
}
Parent5.prototype.say = function () {
console.log('hello5');
};
Child5.prototype = Object.create(Parent5.prototype);
Child5.prototype.constructor = Child5;
var s9 = new Child5();
var s10 = new Child5();
s9.play.push(4);
console.log(s9 instanceof Child5, s9 instanceof Parent5);
console.log(s9.constructor, s10.constructor, s9.hasOwnProperty('play'), 'test11');
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。