这篇原本应该是做为写JS
面向对象的前奏,只是做为《javascript高级程序设计》继承一章的笔记javascript
原型链java
code
实现shell
function SuperType() { this.colors = ['red','blue', 'green']; } function SubType() { } SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push("black"); console.log(instance1.colors); // ['red','blue', 'green','black'] var instance2 = new SubType(); console.log(instance2.colors); // ['red','blue', 'green','black'] var instance = new SuperType(); console.log(instance.colors); // ['red','blue', 'green']
借用构造函数segmentfault
code
实现继承函数
function SuperType() { this.colors = ["red","blue","green"]; } function SubType() { SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push("black"); console.log(instance1.colors); // ["red", "blue", "green", "black"] var instance2 = new SubType(); console.log(instance2.colors); // ["red", "blue", "green"] var instance = new SuperType(); console.log(instance.colors); // ['red','blue', 'green']
一样也能够实现参数的传递this
function SuperType(name) { this.name = name; } function SubType(){ SuperType.call(this, "jack"); this.age = 29; } var instance = new SubType(); console.log(instance.name); // jack console.log(instance.age); // 29
组合继承prototype
code
实现设计
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); }; var instance1 = new SubType("jack", 29); instance1.colors.push("black"); console.log(instance1.colors); //["red", "blue", "green", "black"] instance1.sayName(); // jack instance1.sayAge(); // 29 var instance2 = new SubType("allen", 23); console.log(instance2.colors); // ["red", "blue", "green"] instance2.sayName(); //allen instance2.sayAge(); // 23
instanceOf
和isPrototypeOf
也可以用于识别基于组合继承建立的对象原型式继承code
没有严格意义上的构造函数,经过借助原型,能够基于已有的对象建立新对象,同时还没必要所以建立自定义类型对象
function object(o){ function F(){}; F.prototype = o; return new F(); }
在object()
函数内部,先建立了一个临时性的构造函数,而后将传入的对象做为这个构造函数的原型,最后返回这个临时类型的一个新实例。从本质上将,object()
对传入其中的对象执行了一次浅复制
function object(o) { function F() {}; F.prototype = o; return new F(); } var person = { name:'jack', friends:['allen','lucy','van'] } var anotherPerson = object(person); anotherPerson.name = 'bob'; anotherPerson.friends.push('steve'); var yetAnotherPerson = object(person); yetAnotherPerson.name = 'linda'; yetAnotherPerson.friends.push('shelly') console.log(person.friends); //["allen", "lucy", "van", "steve", "shelly"]
这种原型式继承,要求你必须有一个对象能够做为另外一个对象的基础。若是有这么一个对象的话,能够把他传递给object()
函数,而后再根据具体需求对获得的对象加以修饰便可。
ECMAScript5
经过Object.create()
方法规范花了原型式继承。这个方法接受两个参数:一个用做新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。在传入一个参数的状况下,Object,create()
与object()
函数方法的行为相同
在没有必要建立构造函数,而只是想让一个对象与另外一个对象保持相似的状况下,原型式继承是彻底能够胜任的。不过,包含引用类型值的属性始终都会共享响应的值,就像使用原型模式同样
寄生式继承
寄生式继承是与原型式继承紧密相关的一种思路。寄生式继承的思路与寄生构造函数和工厂模式相似,即建立一个仅用于封装继承过程的函数,该函数在内部已某种方式来加强对象,最后再像真的是它作了全部工做同样返回对象。
function createAnother(original){ var clone = object(original); // 经过调用 object() 函数建立一个新对象 clone.sayHi = function(){ // 以某种方式来加强对象 alert("hi"); }; return clone; // 返回这个对象 }
object()
函数不是必需的;任何可以返回新对象的函数都使用与此模式。寄生组合式继承
JavaScript
最经常使用的继承模式;不过也有本身的不足。组合继承最大的问题就是不管什么状况下,都会调用两次父类的构造函数:一次是在建立子类原型的时候,另外一次是在子类构造函数内部。子类最终会包含父类对象的所有实例属性,但咱们不得不在调用子类构造函数时重写这些属性。
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); // 第二次调用 SuperType() this.age = age; } SubType.prototype = new SuperType(); // 第一次调用 SuperType() SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function() { console.log(this.age); };
第一次调用SuperType
构造函数时,SubType.prototype
会获得两个属性:name
和colors
,他们都是SuperType
的实例属性,只不过如今位于SubType
的原型中。当调用SubType
构造函数时,又会调用一次SuperType
构造函数,这一次又在新对象上建立了实例属性name
和colors
。 因而,这两个属性就屏蔽了原型中的两个同名属性。
所谓寄生组合式继承,即经过借用构造函数来继承属性,经过原型链的混成形式来继承方法。其背后的基本思路是:没必要为了指定子类的原型而调用父类的构造函数,咱们所须要的无非就是父类原型的一个副本而已。本质上,就是使用寄生式继承来继承父类型的原型,而后再将结果指定给子类的原型。寄生组合式继承的基本模式以下
function inheritPrototype(subType, superType) { var prototype = object(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; }
第一步是建立父类原型的一个副本,第二步是为建立的副本添加constructor
属性,从而弥补因重写原型而失去的默认的constructor
属性。第三步是将新建立的对象(即副本)赋值给子类的原型。
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); // 第二次调用 SuperType() this.age = age; } inheritPrototype(SubType, SuperType) SubType.prototype.sayAge = function() { console.log(this.age); };
这个例子的高效率体如今它只调用了一次SuperType
构造函数,而且所以避免了在SubType.prototype
上建立没必要要的、多余的属性。于此同时,原型链还能保持不变;所以,还可以正常使用instanceof
和isPrototypeOf()
。开发人员广泛认为寄生组合继承是引用类型最理想的继承范式。
constructor
属性,从而弥补因重写原型而失去的默认的constructor
属性。第三步是将新建立的对象(即副本)赋值给子类的原型。
JS
面向对象系列