摘要:通过方法或方法也可以,实质上是在未来将要新创建的实例的环境下调用构造函数。组合继承指的是将原型链继承和借用构造函数继承的技术组合到一块,从而发挥二者之长的一种继承模式。该模式通过借用构造函数继承属性,通过重新子类型继承方法。
原型链继承
function SuperType() { this.property = true; } // 在原型链上定义方法。 SuperType.prototype.getSuperValue = function (){ return this.property; } function SubType() { this.subproperty = false; } // 替换SubType原型,达到继承效果。 SubType.prototype = new SuperType(); // 开始写SubType的方法,注:SubType的方法必须写在替换SubType原型语句后 SubType.prototype.getSubValue = function (){ return this.subproperty; } var instance = new SubType(); alert(instance.getSuperValue());
原型链继承的原理如期名,是利用创建父类(SuperType)的实例,并将该实例赋值给子类(SubType).prototype实现的,实质是重写子类的原型对象。
原型链继承特点:
引用类型值的原型属性会被所有实例共享。
在创建子类型的实例时,没办法再不影响所有对象实例的情况下向超类传递参数。
即实现所有属性方法共享,但无法做到属性、方法独享。
借用构造函数继承function SuperType() { this.colors = ["red","blue","green"]; } function SubType() { //继承属性 SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors); //red,blue,green,black var instance2 = new SubType(); alert(instance2.colors); //red,blue,green
借用构造函数继承(constructor stealing),该继承思想很简单,即在子类型构造函数的内部调用超类型构造函数即可。通过call()方法(或apply()方法也可以),实质上是在(未来将要)新创建的SubType实例的环境下调用SuperType构造函数。
借用构造函数继承特点:
可以在子类型构造函数中向超类型构造函数传递参数。
方法都在构造函数中定义,无法实现函数复用。
超类型的原型中定义的方法对子类不可见。
即实现所有属性独享,但无法做到方法继承。
组合继承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); //第二次调用SuperType this.age = age; } //继承方法 SubType.prototype = new SuperType(); //第一次调用SuperType SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); } var instance1 = new SubType("Y",21); instance1.colors.push("black"); alert(instance1.colors); //red,blue,green,black instance1.sayName(); //Y instance1.sayAge(); //21 var instance2 = new SubType("Z",22); alert(instance2.colors); //red,blue,green instance2.sayName(); //Z instance2.sayAge(); //22
组合继承(combination inheritance)又叫伪经典继承,是JavaScript中最常用的继承模式。组合继承指的是将原型链继承和借用构造函数继承的技术组合到一块,从而发挥二者之长的一种继承模式。该模式通过借用构造函数继承属性,通过重新子类型prototype继承方法。
组合继承特点:
实现了所有方法共享,属性独享。
instanceof()和isprototypeOf()能够识别基于组合继承创建的对象。
实现的时候调用了两次超类(父类),产生多余属性。
原型式继承// 工具函数,实质是对传入的对象执行一次浅拷贝。 function object(o) { function F() {} F.prototype = o; return new F(); } var person = { name:"Y", friends:["S","C","V"], say:function () { alert(this.friends); } }; var anotherPerson = object(person); anotherPerson.name = "G"; anotherPerson.friends.push("R"); var yetAnotherPerson = object(person); yetAnotherPerson.name = "L"; yetAnotherPerson.friends.push("B"); person.friends.push("my"); anotherPerson.say(); //S,C,V,R,B,my alert(person.friends); //S,C,V,R,B,my
原型式继承是由道格拉斯·克罗克福德提出的,该模式要求你必须有一个对象可以作为另外一个对象的基础。该模式将一个对象传递给object()函数,然后再根据具体需求对得到的对象加以修改即可。
原型式继承特点:
以传入object的对象为原型,拷贝一个副本并反回。
做不到函数复用,导致效率低。
对象的引用类型所有实例共享(person的引用类型friends不仅属于person所有,而且也会被antherPerson和yetAnotherPerson共享)。
寄生式继承function object(o) { function F() {} F.prototype = o; return new F(); } function createAnother(original) { var clone = object(original); clone.sayHi = function (){ alert(this.friends); }; return clone; } var person = { name:"Y", friends:["S","C","V"] }; var anotherPerson = createAnother(person); anotherPerson.friends.push("test"); anotherPerson.sayHi(); var anotherPerson2 = createAnother(person); anotherPerson2.sayHi();
寄生式继承(parasitic)同样是由克罗克福德提出并推广而之的。该模式创建一个仅用于封装继承过程的函数,该函数的内部以某种方式增强对象,最后再像真地式它做了所有工作一样返回对象。
寄生式继承特点:
做不到函数复用,导致效率低。
对象的引用类型所有实例共享。
寄生组合式继承function object(o) { function F() {} F.prototype = o; return new F(); } // 将超类型的prototype浅拷贝一遍并赋值给子类型的prototype // (相当于利用超类型prototype重写子类型prototype以达到继承效果) 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 = age; } //继承方法 inheritPrototype(SubType,SuperType); SubType.prototype.sayAge = function(){ alert(this.age); } var instance1 = new SubType("Y",21); instance1.colors.push("black"); alert(instance1.colors); //red,blue,green,black instance1.sayName(); //Y instance1.sayAge(); //21 var instance2 = new SubType("Z",22); alert(instance2.colors); //red,blue,green instance2.sayName(); //Z instance2.sayAge(); //22
原理如图:
寄生组合式继承解决了组合继承最大的问题——无论什么情况下,都会调用两次超类型构造函数。该模式思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需的无非就是超类型原型的副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。
寄生组合式继承特点:
实现了所有方法共享,属性独享。
instanceof()和isprototypeOf()能够识别基于组合继承创建的对象。
参考自《JavaScript高级程序设计》
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/108997.html
摘要:这正是我们想要的太棒了毫不意外的,这种继承的方式被称为构造函数继承,在中是一种关键的实现的继承方法,相信你已经很好的掌握了。 你应该知道,JavaScript是一门基于原型链的语言,而我们今天的主题 -- 继承就和原型链这一概念息息相关。甚至可以说,所谓的原型链就是一条继承链。有些困惑了吗?接着看下去吧。 一、构造函数,原型属性与实例对象 要搞清楚如何在JavaScript中实现继承,...
摘要:中的继承并不是明确规定的,而是通过模仿实现的。继承中的继承又称模拟类继承。将函数抽离到全局对象中,函数内部直接通过作用域链查找函数。这种范式编程是基于作用域链,与前面讲的继承是基于原型链的本质区别是属性查找方式的不同。 这一节梳理对象的继承。 我们主要使用继承来实现代码的抽象和代码的复用,在应用层实现功能的封装。 javascript 的对象继承方式真的是百花齐放,属性继承、原型继承、...
摘要:继承前言作为一门轻量级的脚本语言在和的横空出世之后将其推向的新的高度虽然中出现的新的生成对象的类语法格式但依然为的语法糖而我们依然有必要从的原生实现入手来了解它的继承实现方式给出了更加简洁的固定的类声明方式有兴趣的可以查看阮一峰的入门下面给 javascript继承 前言 javascript作为一门轻量级的脚本语言在ES6和node.js的横空出世之后将其推向的新的高度,虽然 ES6...
摘要:我们有了构造函数之后,第二步开始使用它构造一个函数。来个例子这种方式很简单也很直接,你在构造函数的原型上定义方法,那么用该构造函数实例化出来的对象都可以通过原型继承链访问到定义在构造函数原型上的方法。 来源: 个人博客 白话解释 Javascript 原型继承(prototype inheritance) 什么是继承? 学过面向对象的同学们是否还记得,老师整天挂在嘴边的面向对象三大特...
摘要:和构造函数前面提到,是个内置隐藏属性,虽然在可以通过访问,但是其设计本意是不可被读取和修改的,那么我们如何利用原型链来建立继承关系提供了关键字。到这儿,思路就清晰了,怎么让对象和对象的相连实现继承只需把的构造函数的连接到就行了。 什么是继承? 大多数人使用继承不外乎是为了获得这两点好处,代码的抽象和代码的复用。代码的抽象就不用说了,交通工具和汽车这类的例子数不胜数,在传统的OO语言中(...
阅读 3418·2021-11-15 11:39
阅读 1551·2021-09-22 10:02
阅读 1307·2021-08-27 16:24
阅读 3596·2019-08-30 15:52
阅读 3412·2019-08-29 16:20
阅读 823·2019-08-28 18:12
阅读 549·2019-08-26 18:27
阅读 714·2019-08-26 13:32