//原型链继承 function superType() { this.property = true; } superType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false } //继承了subType SubType.prototype = new superType(); SubType.prototype.getSubValue = function () { return this.subproperty }; var instance = new SubType(); alert(instance.getSuperValue()); //true //调用instance.getSuperValue()会经历三个步骤,1:搜索实例,2:搜索SubType.prototype;搜索superType.prototype============== //SubType继承了superType,而superType继承了Object。当调用了instance.toString()时,实际上市保存在Object.prototype中的那个方法
有两种方法确定原型和实例之间的关系
1:实例和原型中的出现过的构造函数都会返回true
alert(instance instanceof Object)//true alert(instance instanceof SuperType)//true alert(instance instanceof SubType)//true
第二种方式是使用 isPrototypeOf(),只要在原型链中出现过的原型。都会返回true; alert(Object.prototype.isPrototypeOf(instance))//true alert(SuperType.prototype.isPrototypeOf(instance))//true alert(SubType.prototype.isPrototypeOf(instance))//true
3:谨慎地定义方法
//原型链继承 function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false } //继承了subType SubType.prototype = new SuperType(); //添加新方法 SubType.prototype.getSubValue = function () { return this.subproperty }; //重写超类型中的方法 SubType.prototype.getSuperValue = function () { return false } var instance = new SubType(); alert(instance.getSuperValue()); //false
使用对象字面量会导致错误,刚刚把SuperType的实例赋给了原型,紧接着又将原型替代成一个对象字面量导致原型链被切断,现在的原型包含一个Object实例,而非SuperType的实例,因此我们设想中的原型链已经被切断--SubType和SuperType之间已经没有关系了
//原型链继承 function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = function(){ return this.property; }; function SubType(){ this.subproperty = false } //继承了subType SubType.prototype = new SuperType(); //使用对象字面量 会使上一行代码无效 SubType.prototype = { getSubValue : function () { return this.subproperty }; } var instance = new SubType(); alert(instance.getSuperValue()); //false
原型链的问题
1:原型属性会被所有实例共享;
2:没有办法在不影响对象实例的情况下,给超类型的构造函数传递参数
function SuperType() { this.colors = ["red","blue","green"]; } function SubType(){ } //继承了subType SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors) var instance2 = new SubType(); alert(instance2.colors)//["red","blue","green","black"];
借用构造函数,函数复用无从谈起。
function SuperType() { this.colors = ["red","blue","green"]; } function SubType(){ //继承了subType SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors) var instance2 = new SubType(); alert(instance2.colors)//["red","blue","green"];
传递参数
function SuperType(name) { this.name = name } function SubType(){ //继承了superType,同时还传递了参数 SuperType.call(this,"gay"); //实例属性 this.age = 29; } var instance = new SubType(); alert(instance.name)//gay alert(instance.age)//29
组合继承,有时候也称为伪经典继承,指的是将原型链和构造函数的技术组合到一块。。思路:使用原型链实现对原型属性和方法的继承,而通过构造函数来实现对实例属性的继承。使用最多的方法
function SuperType(name) { this.name = name; this.colors = ["red","blue","green"]; } SuperType.prototype.sayName = function () { alert(this.name) } function SubType(name,age){ //继承属性 SuperType.call(this,name); //实例属性 this.age = 29; } //继承方法 SubType.prototype = new SuperType(); SubType.prototype.sayAge = function () { alert(this.age) } var instance1 = new SubType("gay",29); instance1.colors.push("black"); alert(instance1.colors)//"red","blue","green","black" instance1.sayName();//"gay" instance1.sayAge();//29 var instance2 = new SubType("blue",27); alert(instance2.colors)//"red","blue","green" instance2.sayName();//"blue" instance2.sayAge();//27
原型式继承
//ES5通过新增的Object.creat()方法规范化了原型式继承。这个方法接受两个参数,一个用作新对象原型的对象和(可选的)一个为新对象定义额外的对象。 var person = { name:"gay"; friend:["1","2","3"] }; //第二个参数可有可无,和Object.defineProperties()方法的第二个参数格式相同 var anotherPerson = Object.creat(person,{ name:{ value:"blue" } }) //在没有必要兴师动众地创建构造函数,而只想让一个对象和另外一个对象保持类似的情况下,原型式继承是完全可以胜任的。
寄生组合式继承
function inheritPrototype(subType,superType){ var prototype = object(superType.prototype); prototype.constructor = subType; subType.prototype = prototype; }; function superType(name) { this.name = name; this.colors = ["red","blue","green"]; } superType.prototype.sayName = function () { alert(this.name) } function subType(name,age){ //继承属性 SuperType.call(this,name); //实例属性 this.age = 29; } inheritPrototype(subType,superType); subType.prototype.sayAge = function () { alert(this.age) } //这个例子只调用了一次SuperType构造函数,并且因此避免了在SubType.prototype上面创建不必要的多余的属性。与此同时,原型链还能保持不变,因此,还能正常的使用instanceof和isPrototype()。寄生组合式继承是引用类型最理想的继承规范