一、创建对象的方式
1、工厂模式:用函数来封装,以特定接口创建对象
工厂模式解决了创建多个相似对象的问题,但没有解决对象识别的问题(判断对象的类型)。
eg:
function createPerson(name, age) {
var o = new Object()
o.name = name
o.age = age
o.sayName = function () {
console.log(this.name)
}
return o;
}
var person1 = createPerson("Jack", 23)
var person2 = createPerson("Mei", 33)
2、构造函数模式:
构造函数模式的问题:每个方法都要在每个实例上重新创建一遍,浪费内存。
function Person(name, age) {
this.name = name
this.age = age
this.sayName = function () {
console.log(this.name)
}
}
var person1 = new Person("Jack", 23)
var person2 = new Person("Mei", 33)
此构造函数和上面的工厂函数的区别:
(1)没有显示地创建对象;
(2)直接将属性和方法赋给this对象;
(3)没有return语句;
(4)创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型,而这正是构造函数模式胜过工厂模式的地方。
3、原型模式:所有对象实例共享原型对象包含的属性和方法。
function Person() {};
Person.prototype = {
constructor: Person,
name: ‘Jack‘,
age: 28,
job: ‘Java‘,
sayName: function() {
console.log(this.name);
}
};
var person1 = new Person()
var person2 = new Person()
原型模式的主要问题:
(1)省略了为构造函数传递初始化参数这一环节, 结果所有实例在默认情况下都将取得相同的属性值。
(2)这还不是最大的问题,最大的问题是:由其共享的本性所导致的(对于包含引用类型值的属性来说,问题比较突出)
eg:

3.2原型与in操作符
(1)in单独用:在对象能够访问到属性时返回true,无论属性存在于实例中还是原型中。
(2)for-in:返回可返问,可枚举的实例和原型上的属性。
4、组合使用构造函数和原型模式:
Javascript中创建自定义对象最常见的方式,是组合使用构造函数和原型模式,构造函数模式用于定义实例属性,原型模式用于定义方法和共享属性。
每个实例都存有自己的一份实例属性副本,又共享着对方法的引用,最大限度节省了内存。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
}
Person.prototype.sayName = function() {
console.log(this.name);
};
5、动态原型模式:把所有信息封装在构造函数中,通过在构造函数中初始化原型(仅在必要的情况下),又保持了同时使用构造函数和原型的优点。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
if(typeof this.sayName != ‘function‘) {
Person.prototype.sayName = function() {
console.log(this.name);
};
}
}
6、寄生构造函数模式:创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象。除了使用new操作符并把使用的包装函数叫做构造函数外,这个模式跟工厂模式一模一样。
构造函数在不返回值的情况下,默认会返回新对象实例;而通过在构造函数的末尾添加一个return语句,可以重写调用构造函数时的返回值。
寄生构造函数模式,适合在某些特殊情况下,为对象创建额外的方法。
弊端:不能依赖instanceof操作符来确定对象类型。
function Person(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
console.log(o.name);
};
ruturn o;
}
var person = new Person(‘Jack‘, 28, ‘Java‘);
7、稳妥构造函数模式:
道格拉斯·克罗克福德发明了JS中的稳妥对象,所谓稳妥对象,指的是没有公用属性,而且其方法也不引用this的对象。
稳妥构造函数模式适合在某些安全执行环境中(这些环境禁止使用this和new)使用。
function Person(name, age, job) {
var o = new Object();
// 定义私有变量和函数
// 暴露个外部的唯一访问入口
o.sayName = function() {
console.log(name);
};
return o;
}
var person = Person(‘Jack‘, 28, ‘Java‘);
person.sayName();
8、ES6 class

二、继承【OOP的方式】
1、原型(链)
(1)OO语言支持两种继承:接口继承和实现继承,接口继承只继承方法签名,实现继承则继承实际的方法。ECMAScript只支持实现继承,而且其实现继承主要通依靠型链实现。
(2)原型链的基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
(3)原型链的构建是通过将一个引用类型的实例赋值给另一个构造函数的原型实现的。
function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function() {
return this.property;
};
function SubType() {
this.subProperty = false;
}
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function() {
return this.subProperty;
};
var instance = new SubType();
console.log(insctance.getSuperValue()); // true
原型链的问题:
1)由其共享的本性所导致的引用类型值问题;
2)在创建子类型的实例时,无法在不影响所有对象实例的情况下向超类型的构造函数传递参数。
2、借用构造函数(经典继承)
function SuperType() {
this.friends = [‘Jack‘, ‘Lucy‘];
}
function SubType() {
// 继承SuperType
SuperType.call(this);
}
var instance1 = new SubType();
instance1.friends.push(‘Jim‘);
console.log(instance1.friends); // ‘Jack,Lucy,Jim‘
var instance2 = new SubType();
console.log(instance2.friends); // ‘Jack,Lucy‘
经典继承无法避免构造函数模式存在的问题——方法无法复用。
3、组合继承(伪经典继承)
function SuperType(name) {
this.name = name;
this.friends = [‘Jack‘, ‘Lucy‘];
}
SupperType.prototype.sayHello = function() {
console.log(this.name);
};
function SubType(name, age) {
// 继承SuperType
SuperType.call(this, name);
this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function() {
console.log(this.age);
}
var instance1 = new SubType(‘Jim‘, ‘28‘);
instance1.friends.push(‘David‘);
console.log(instance1.friends); // ‘Jack,Lucy,David‘
instance1.sayHello(); // ‘Jim‘
instance1.sayAge(); // ‘28‘
var instance1 = new SubType(‘Lily‘, ‘26‘);
console.log(instance1.friends); // ‘Jack,Lucy‘
instance1.sayHello(); // ‘Lily‘
instance1.sayAge(); // ‘26‘
组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为ECMAScript中最常用的继承模式。
4、原型式继承
道格拉斯·克罗克福德发明了原型式继承。
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
ECMAScript5通过Object.create()方法规范化了原型式继承。
5、寄生式继承
function createAnother(ori) {
var clone = Object.create(ori);
clone.sayHi = function() {
console.log(‘Hi‘);
};
ruturn clone;
}
6、寄生组合式继承
function inheritPrototype(subType, superType) {
var prototype = Object.create(superType.prototype);
prototype.constructor = subType;
subType.prototype = prototype;
}
寄生组合式继承是引用类型的最佳继承模式。
面向对象
原文:https://www.cnblogs.com/webenjoy/p/12162631.html