摘要:实现继承的方法借用构造函数解决原型中包含引用类型所带来的问题的过程中,使用借用构造函数伪造对象或经典继承来实现继承。
继承
在ECMAScript中继承主要是依靠原型链来实现的。
实现继承的方法
利用原型让一个引用类型继承另一个引用类型的属性和方法什么是原型链
先要了解构造函数、原型、和实例的关系:
每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,实例都包含一个指向原型对象的内部指针。
实现原型链
假如原型对象等于另一个类型的实例,此时该原型对象将包含指向另一个原型的指针,相应的另一个原型中也包含着一个指针指向另一个构造函数的指针。这样层层递进,就构成了实例与原型之间的链条。这就是原型链的基本概念。
判断原型和实例的关系
可以通过两种方式来确定原型和实例之间关系。
使用instanceof操作符,只要用这个操作符来测试实例和原型链中出现的构造函数,结果就一定返回true。
alert(instance instanceof Object); //true
使用isprototypeOf()方法,同样只要是原型链中出现过得原型,都可以说是原型链所派生的实例的原型。isportotypeOf()也会返回true
alert(Object.prototype.isPrototypeOf(instance)); //true
所有引用类型都默认继承了Object
原型链存在的问题
在通过原型来实现继承时,原型实际上会变成另一个类型的实例。原先的实例属性就变成了现在的原型属性了。
function SuperType(){ this.color=["red","blue","green"] } function SubType(){ } SubType.prototype = new SuperType();//继承了SuperType(); var instance1 = new SubType(); instance1.color.push("black"); console.log(instance1.color); //"red,blue,green,black" var instance2 = new SubType(); console.log(instance2.color); //"red,blue,green,black"
SuperType构造函数定义了一个colors属性,SuperType的每个实例都会有各自包含自己数组的color属性。当SubType通过原型链继承了SuperType之后,subType.prototype就变成了SuperType的一个实例,因此它也就拥有了自己的color属性。那SubType的所有实例都会共享这个color属性。 2. 在创建子类型的实例时,不能向超类型的构造函数中传递参数。实现继承的方法 1. 借用构造函数
解决原型中包含引用类型所带来的问题的过程中,使用借用构造函数(伪造对象或经典继承)来实现继承。主要是通过使用apply()和call()方法在新创建的对象上执行构造函数如下:
function SuperType(){ this.color=["red","blue","green"] } function SubType(){ //继承了SuperType SuperType.call(this); } var instance1 = new SubType(); instance1.color.push("black"); console.log(instance1.color) //"red, blue,green,black" var instance2 = new SubType(); console.log(instance2.color) //"red,blue,green"
通过call()或apply()方法在新创建的SubType实例的环境下调用了SuperType构造函数
相对原型链,借用构造函数可以子类型构造函数中向超类型构造函数传递参数如下:
function SuperType(name){ this.name=name; } function SubType(){ //继承了SuperType 同时还传递了参数 SuperType.call(this,"aa"); //实例属性 this.age=29; } var instance = new SubType(); alert(instance.name) // aa alert(instance.age) //29
### 2. 组合继承
组合继承也叫做伪经典继承将原型链和借用构造函数的技术组合到一块,从而发挥二组之所长的一种继承模式。思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。
function SuperType(name){ this.name=name; this.color = ["red","blue","green"] }; SuperType.prototype.sayName = function(){ alert(this.name) }; function SubType(name,age){ //继承属性 SuperType.call(this,name); this.age=age; } //继承方法 SubType.prototype = new SuperType(); SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); }; var instance1 = new SubType("aaa",29); instance1.color.push("black"); alert(instance1.color); //"red,blue,green,black" instance1.sayName(); //"aaa" instance1.sayAge(); // 29 var instance2 = new SubType("ccc",30); alert(instance2.color); //"red,blue,green" instance2.sayName(); //"ccc" instance2.sayAge(); // 30
组合继承避免了原型链和借用构造函数的缺陷,融合了他们的优点,成为JavaScript中最常用的继承模式。而且instanceOf和isPrototype()也能够识别基于组合继承创建的对象。
### 3. 原型式继承
借用原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。
var person = { name:"Nicholas", friends:["Shelby","court","Van"] }; var anotherPerson = Object.create(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob"); var yetAnotherPerson = Object.create(person); yetAnotherPerson.name = "Linda"; yetAnotherPerson.friends.push("Barbie"); alert(person.friends) //"Shelby,Count,Van,Rob,Barbie"
Object.create()传递第二个参数
var person = { name: "Nicholas", friends: ["Shelby","Court","Van"] } var anotherPerson = Object.create(person,{ name: { value: "Greg" } }); var anotherPerson2 = Object.create(person,{ name: { value: "blue" } }); alert(anotherPerson.name) //"Greg" alert(anotherPerson2.name) //"blue"
Obeject.create()方法IE9开始兼容
### 4. 寄生式继承
寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像·真地是它做了所有工作一样返回对象。
function createAnother(original) { var clone = object(original); clone.sayHi = function(){ alert("hi"); }; return clone; } var person = { name: "Nicholas", friends: ["Shelby","Court","Van"] }; var anotherPerson = createAnother(person); anotherPerson.sayHi(); //"hi"
本文主要是个人摘自《javascript高级程序设计》用来做个人笔记的,请大佬们手下留情。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/106981.html
摘要:原型链实现继承例子继承了借用构造函数基本思想在子类型构造函数的内部调用超类构造函数,通过使用和方法可以在新创建的对象上执行构造函数。 前言:大多OO语言都支持两种继承方式:接口继承和实现继承,而ECMAScript中无法实现接口继承,ECMAScript只支持实现继承,而且其实现继承主要是依靠原型链来实现。 1.原型链 基本思想:利用原型让一个引用类型继承另外一个引用类型的属性和方法。...
摘要:原型继承缺点子类实例共享属性,造成实例间的属性会相互影响可以看到子类的实例属性皆来自于父类的一个实例,即子类共享了同一个实例共享了父类的方法构造函数继承缺点父类的方法没有被共享,造成内存浪费子实例的属性都是相互独立的实例方法也是独立的,没有 原型继承 缺点: 子类实例共享属性,造成实例间的属性会相互影响 function Parent1() { this.name = [super...
摘要:基于原型的继承原型上的属性被共享了不是我们所需要的这种继承会有如下的缺点如果父类包含有引用类型的属性所有的子类就会共享这个属性。 基于原型的继承 function father() { this.faName = father; this.names=[11,22] } father.prototype.getfaName = fun...
摘要:使用最多的继承模式是组合继承,这种模式使用原型链继承共享的属性和方法,而借用构造函数继承实例属性。原型式继承,可以在不必预先定义构造函数的情况下实现继承,其本质是执行给定对象的浅复制。 1、原型链实现继承 function SuperType() { this.property = true; } SuperType.prototype.getSuperValue = func...
摘要:使用关键字熟悉的同学应该非常熟悉这个关键字,中的继承都是靠它实现的。新加入的关键字是语法糖,本质还是函数使用修改之前的例子,将会更简单在下面的例子,定义了一个名为的类,然后定义了一个继承于的类。 使用Object.create实现类式继承 下面是官网的一个例子 //Shape - superclass function Shape() { this.x = 0; this.y ...
阅读 2608·2021-11-18 10:02
阅读 2278·2021-09-30 09:47
阅读 1745·2021-09-27 14:01
阅读 3109·2021-08-16 11:00
阅读 3163·2019-08-30 11:06
阅读 2391·2019-08-29 17:29
阅读 1529·2019-08-29 13:19
阅读 444·2019-08-26 13:54