首页 > 代码库 > javascript之继承

javascript之继承

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

 

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

原型链继承

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

  技术分享

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

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

   具体代码: 

 1    function SuperType() {
 2       this.proterty = true
 3     }
 4     SuperType.prototype.getSuperValue =http://www.mamicode.com/ function () {
 5       return this.proterty
 6     }
 7     function SubType() {
 8       this.subproperty = false
 9     }
10     //继承了SuperType
11     SubType.prototype = new SuperType()
12     SuperType.prototype.getSubValue =http://www.mamicode.com/ function () {
13       return this.subproperty
14     }
15     var instance = new SubType()
16     instance.getSuperValue()  //true

判断原型和实例的关系

使用instance或者isPrototypeOf

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

 

缺点:

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

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

 

借用构造函数

    

 1     function SuberType() {
 2       this.colors = ["red","blur"]
 3     }
 4     function SubType() {
 5       //继承了SuberType 
 6       //使用了call改变了this的作用域,用apply也可以
 7       SuberType.call(this)
 8     }
 9     var instance = new  SubType()
10     instance.colors.push("black")
11     alert(instance.colors) //red,blur,black
13 var instalce2 = new SuberType() 14 alert(instalce2.colors) // red,blur

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

 1      function SuberType(name) {
 2         this.name = name
 3       }
 4       function SubType() {
 5         //继承了SuberType,还传递了参数
 6         SuberType.call(this,"zhao")
 7         this.age = "27"
 8       }
 9       var instance = new SubType()
10       alert(instance.name) //zhao
11       alert(instance.age) //27

缺点:

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

 

组合继承

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

     

 1    function SuberType(name) {
 2       this.name = name
 3       this.colors = ["red","blue"]
 4     }
 5     SuberType.prototype.sayName = function () {
 6       alert(this.name)
 7     }
 8     function SubType(name,age) {
 9       //继承属性
10       SuberType.call(this, name)  // 第一次调用SuberType()
11       this.age = age
12     }
13     //继承方法
14     SubType.prototype = new SuberType()  //第二次调用SuberType()
15     SubType.prototype.sayAge = function () {
16       alert(this.age)
17     }
18     var instance1 = new SubType("zhao", 27)
19     instance1.colors.push("black")
20     alert(instance1.colors) // red,blue,black
21     instance1.sayName() // zhao
22     instance1.sayAge()  //27
23 
24     var instance2 = new SubType("w", 28)
25     alert(instance2.colors) // red,blue
26     instance2.sayName() // w
27     instance2.sayAge() // 28

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

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

 

原型式继承

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

    

1    function object(o) {
2       function F() {}
3         F.prototype = o
4         return new F()6     }

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

 1  var person = {
 2       name: zhao,
 3       friends: [zhao1,zhao2,zhao3]
 4     }
 5     var anotherPerson = object(person)
 6     anotherPerson.name = ss
 7     anotherPerson.friends.push(Bob)
 8 
 9     var yetAnotherPerson = object(person)
10     yetAnotherPerson.name = rr
11     yetAnotherPerson.friends.push(Bar)
12     alert(person.friends) //zhao1,zhao2,zhao3,Bob,Bar

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

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

 1     var person = {
 2       name: zhao,
 3       friends: [zhao1,zhao2,zhao3]
 4     }
 5     var anotherPerson = Object.create(person)
 6     anotherPerson.name = ss
 7     anotherPerson.friends.push(Bob)
 8 
 9     var yetAnotherPerson = Object.create(person)
10     yetAnotherPerson.name = rr
11     yetAnotherPerson.friends.push(Bar)
12     alert(person.friends) //zhao1,zhao2,zhao3,Bob,Bar

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

 1     var person = {
 2       name: zhao,
 3       friends: [zhao1,zhao2,zhao3]
 4     }
 5     var anotherPerson = Object.create(person)
 6     anotherPerson.name = ss
 7     anotherPerson.friends.push(Bob)
 8 
 9     var yetAnotherPerson = Object.create(person)
10     yetAnotherPerson.name = rr
11     yetAnotherPerson.friends.push(Bar)
12     alert(person.friends) //zhao1,zhao2,zhao3,Bob,Bar

 

javascript之继承