主要是参考了《JavaScript高级程序设计(第三版)》这本书,根据自己的理解,做了下面的记录

继承是面向对象(OO)语言里面的概念,有俩种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。由于函数没有签名,在javascript里面无法实现接口继承,只支持实现继承。

原型链继承

构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。

所有函数的默认原型都是Object的实例

那如果让原型对象等于另一个类型的实例会怎么样呢?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型也包含着指向另一个构造函数的指针。

具体代码:

    function SuperType() {
this.proterty = true
}
SuperType.prototype.getSuperValue = function () {
return this.proterty
}
function SubType() {
this.subproperty = false
}
//继承了SuperType
SubType.prototype = new SuperType()
SuperType.prototype.getSubValue = function () {
return this.subproperty
}
var instance = new SubType()
instance.getSuperValue() //true

判断原型和实例的关系

使用instance或者isPrototypeOf

     alert(instance instanceof SubType)  //  true
alert(SubType.prototype.isPrototypeOf(instance)) // true

缺点:

(一)、只要某个实例、构造函数、原型对象修改了属性或方法,会对原型链上的其他对象实例造成影响

(二)、在创建了类型的实例时,没有办法在不影响谁有对象实例的情况下,给超类型的构造函数传递参数

借用构造函数

     function SuberType() {
this.colors = ["red","blur"]
}
function SubType() {
//继承了SuberType
//使用了call改变了this的作用域,用apply也可以
SuberType.call(this)
}
var instance = new SubType()
instance.colors.push("black")
alert(instance.colors) //red,blur,black
 var instalce2 = new SuberType()  alert(instalce2.colors) // red,blur

优点:可以在子类型构造函数中向超类型构造函数传递参数

      function SuberType(name) {
this.name = name
}
function SubType() {
//继承了SuberType,还传递了参数
SuberType.call(this,"zhao")
this.age = ""
}
var instance = new SubType()
alert(instance.name) //zhao
alert(instance.age) //

缺点:

方法都在构造函数中定义,函数无法复用。而且在超类型的原型中定义的方法,子类型是不可见的

组合继承

原型链和构造函数的技术组合到一起。思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承

    function SuberType(name) {
this.name = name
this.colors = ["red","blue"]
}
SuberType.prototype.sayName = function () {
alert(this.name)
}
function SubType(name,age) {
//继承属性
SuberType.call(this, name) // 第一次调用SuberType()
this.age = age
}
//继承方法
SubType.prototype = new SuberType() //第二次调用SuberType()
SubType.prototype.sayAge = function () {
alert(this.age)
}
var instance1 = new SubType("zhao", )
instance1.colors.push("black")
alert(instance1.colors) // red,blue,black
instance1.sayName() // zhao
instance1.sayAge() // var instance2 = new SubType("w", )
alert(instance2.colors) // red,blue
instance2.sayName() // w
instance2.sayAge() //

优点:实例有各自的属性,和相同的方法

缺点:会俩次调用超类型的构造函数

原型式继承

借助原型可以基于已有的对象创建新对象,不必因此自定义类型

    function object(o) {
function F() {}
F.prototype = o
return new F() }

上面这个函数的本质是:object()对传入的对象执行了一次浅复制

  var person = {
name: 'zhao',
friends: ['zhao1','zhao2','zhao3']
}
var anotherPerson = object(person)
anotherPerson.name = 'ss'
anotherPerson.friends.push('Bob') var yetAnotherPerson = object(person)
yetAnotherPerson.name = 'rr'
yetAnotherPerson.friends.push('Bar')
alert(person.friends) //zhao1,zhao2,zhao3,Bob,Bar

ECMAScript5通过新增Object.create()方法规范了原型式继承,这个方法接收俩个参数,一个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象

在传入一个参数的情况下,Object.create()和object()一样

     var person = {
name: 'zhao',
friends: ['zhao1','zhao2','zhao3']
}
var anotherPerson = Object.create(person)
anotherPerson.name = 'ss'
anotherPerson.friends.push('Bob') var yetAnotherPerson = Object.create(person)
yetAnotherPerson.name = 'rr'
yetAnotherPerson.friends.push('Bar')
alert(person.friends) //zhao1,zhao2,zhao3,Bob,Bar

Object.create()的第二个参数会覆盖原型对象上的同名属性

     var person = {
name: 'zhao',
friends: ['zhao1','zhao2','zhao3']
}
var anotherPerson = Object.create(person)
anotherPerson.name = 'ss'
anotherPerson.friends.push('Bob') var yetAnotherPerson = Object.create(person)
yetAnotherPerson.name = 'rr'
yetAnotherPerson.friends.push('Bar')
alert(person.friends) //zhao1,zhao2,zhao3,Bob,Bar

寄生式继承

思路:创建一个仅用与封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象

 <script>
function object(o) {
function F() {}
F.prototype = o
return new F()
} function createAnother(original) {
var clone = object(original) // 通过调用函数创建一个新对象
clone.sayHi = function () { // 以某种方式来增强这个对象
alert("hi")
}
return clone //返回这个对象
}
var person = {
name: "zhaobao",
friends: ["zhaobao1","zhaobao2","zhaobao3"]
}
var anotherPerson = createAnother(person)
anotherPerson.sayHi() // hi
</script>

寄生组合式继承

这个主要是为了解决组合继承的缺点

思路:通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。

不必为了指定子类型的原型而调用超类型的构造函数,我们需要的只是超类型原型的一个副本。

本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。

基本模式

   function inheritPrototype(subType, superType) {
var prototype = object(superType) //创建对象
prototype.constructor = subType // 增强对象
subType.prototype = prototype //指定对象
}

例子

 function inheritPrototype(subType, superType) {
var prototype = object(superType) //创建对象
prototype.constructor = subType // 增强对象
subType.prototype = prototype //指定对象
}
function SuperType(name) {
this.name = name
this.colors = ["red","blue"]
}
SuperType.prototype.sayName = function () {
alert(this.name)
}
function SubType(name,age) {
SuperType.call(this,name)
this.age = age
}
inheritPrototype(SubType,SuperType)
SuperType.prototype.sayAge = function () {
alert(this.age)
}

这个例子的高效率提现在它只调用了一次SuperType构造函数,并且因此避免了在SubType.prototype上面创建不必要的、多余的属性。与此同时,原型链还能保持不变,因此,还能正常使用instanceof和isPrototypeOf()

这是最理想的继承方式

javascript之继承的更多相关文章

  1. Javascript模拟继承(赠送.net吐槽一段)

    首先吐槽一句,今年的就业形势很不乐观啊,特别是搞.net的(相对java),特特别是还没出校门没有正式工作经验的,找个实习很难,前些天接了个面试电话,上来就质疑我“你一个在校大学生怎么可能做了那么多项 ...

  2. 详解Javascript的继承实现(二)

    上文<详解Javascript的继承实现>介绍了一个通用的继承库,基于该库,可以快速构建带继承关系和静态成员的javascript类,好使用也好理解,额外的好处是,如果所有类都用这种库来构 ...

  3. JavaScript之继承(原型链)

    JavaScript之继承(原型链) 我们知道继承是oo语言中不可缺少的一部分,对于JavaScript也是如此.一般的继承有两种方式:其一,接口继承,只继承方法的签名:其二,实现继承,继承实际的方法 ...

  4. javascript深度克隆与javascript的继承实现

    1.javascript深度克隆: //注意这里的对象包括object和array function cloneObject(obj){ var o = obj.constructor === Arr ...

  5. 再谈javascript原型继承

    Javascript原型继承是一个被说烂掉了的话题,但是自己对于这个问题一直没有彻底理解,今天花了点时间又看了一遍<Javascript模式>中关于原型实现继承的几种方法,下面来一一说明下 ...

  6. TDD测试驱动的javascript开发(3) ------ javascript的继承

    说起面向对象,人们就会想到继承,常见的继承分为2种:接口继承和实现继承.接口继承只继承方法签名,实现继承则继承实际的方法. 由于函数没有签名,在ECMAScript中无法实现接口继承,只支持实现继承. ...

  7. 彻底理解Javascript原型继承

    彻底理解Javascript原型继承 之前写过一篇Javascript继承主题的文章,这篇文章作为一篇读书笔记,分析的不够深入. 本文试图进一步思考,争取彻底理解Javascript继承原理 实例成员 ...

  8. Javascript原型继承容易忽略的错误

    编写Javascript的开发者都知道,JS虽然没有类(ES6添加了class语法),但是可以模拟出OOP语言的类和面向对象的概念,比如我们都知道的一句话,Javascript中处处是对象,而面向对象 ...

  9. JavaScript类继承, 用什么方法好

    JavaScript类继承, 用什么方法好 一个实例: 基类Car: function Car(color, year) { this.name = "car"; this.col ...

  10. [转]Javascript原型继承

    真正意义上来说Javascript并不是一门面向对象的语言,没有提供传统的继承方式,但是它提供了一种原型继承的方式,利用自身提供的原型属性来实现继承.Javascript原型继承是一个被说烂掉了的话题 ...

随机推荐

  1. Majority Element问题---Moore's voting算法

    Leetcode上面有这么一道难度为easy的算法题:找出一个长度为n的数组中,重复次数超过一半的数,假设这样的数一定存在.O(n2)和O(nlog(n))(二叉树插入)的算法比较直观.Boyer–M ...

  2. k8s kubectl edit 方式修改 nodeport 的端口

    0. 买了一本 每天五分钟玩转 k8s 还有 刚才转帖的blog 里面有一个 kubectl edit 的语法能够在线更改端口号 ,之前一直没弄明白. 刚才做了下实验.发现很好用 这里记录一下. 1. ...

  3. 常用的cpl 命令 运行直接打开控制台的简单方法

    转载百度百科   工作中处理 windows机器 有时候 打开 网路修改ip地址特别繁琐,所以找了下 快速打开一些简单的控制台 能提高工作效率.   (Control Panel extension) ...

  4. Python [练习题] :字典扁平化

    习题:将source字典扁平化,输出为 target 格式的字典.source = {'a': {'b': 1, 'c': 2}, 'd': {'e': 3, 'f': {'g': 4}}}targe ...

  5. poj2559 Largest Rectangle in a Histogram(单调栈)

    Description A histogram is a polygon composed of a sequence of rectangles aligned at a common base l ...

  6. Linux_MySql_tar_安装(转)

    系统版本:CentOs 7.* Mysql版本:5.7.17(自己测试版本) 根据博主[大大的橙子]博文转载记录(大部分照搬了,只修改少许部分) 一.基本环境部署 #卸载系统自带的Mariadb [r ...

  7. Java 8新特性之 Nashorn(八恶人-6)

    Joe Gage 盖奇·乔 “First time in my life I made a pretty penny.And, figured I'd come home and spend time ...

  8. 点分治&动态点分治小结

    (写篇博客证明自己还活着×2) 转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/8006488.html 有的时候,我们会发现这样一类题:它长得很像一个$O(n) ...

  9. MT【75】考察高斯函数的一道高考压轴题

    解答:答案1,3,4. 这里关于高斯函数$[x]$的一个不等式是需要知道的$x-1<[x]\le x$,具体的:

  10. MySQL删除所有表的外键约束、禁用外键约束

    转: MySQL删除所有表的外键约束.禁用外键约束 2017年10月27日 00:11:34 李阿飞 阅读数:4512   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...