快捷搜索:
来自 新京葡娱乐场网址 2019-06-15 16:29 的文章
当前位置: 67677新澳门手机版 > 新京葡娱乐场网址 > 正文

新京葡娱乐场网址:JS的六种继承方式,六种继承

JavaScript 多种持续格局

2017/06/20 · JavaScript · 继承

原稿出处: Xuthus Blog   

接轨是面向对象编制程序中又一不行首要的定义,JavaScript援救促成持续,不支持接口承袭,实现延续首要依赖原型链来达成的。

后续是面向对象编制程序中又一相当重大的概念,JavaScript帮助促成持续,不扶助接口承继,完成三番五次首要依赖原型链来达成的。

原型链

先是得要掌握如何是原型链,在一篇小说看懂proto和prototype的涉及及界别中讲得要命详细

原型链承袭基本思维就是让贰个原型对象指向另三个项指标实例

function SuperType() { this.property = true } SuperType.prototype.getSuperValue = function () { return this.property } function SubType() { this.subproperty = false } SubType.prototype = new SuperType() SubType.prototype.getSubValue = function () { return this.subproperty } var instance = new SubType() console.log(instance.getSuperValue()) // true

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function SuperType() {
  this.property = true
}
SuperType.prototype.getSuperValue = function () {
  return this.property
}
function SubType() {
  this.subproperty = false
}
SubType.prototype = new SuperType()
SubType.prototype.getSubValue = function () {
  return this.subproperty
}
var instance = new SubType()
console.log(instance.getSuperValue()) // true

代码定义了四个体系SuperType和SubType,各类项目分别有一个属性和三个方法,SubType承继了SuperType,而继续是由此创办SuperType的实例,并将该实例赋给SubType.prototype完成的。

金玉锦绣的实质是重写原型对象,代之以贰个新类型的实例,那么存在SuperType的实例中的全数属性和章程,现在也存在于SubType.prototype中了。

小编们清楚,在开创二个实例的时候,实例对象中会有二个里头指针指向创设它的原型,实行关联起来,在此处代码SubType.prototype = new SuperType(),也会在SubType.prototype创制三个中间指针,将SubType.prototype与SuperType关联起来。

故而instance指向SubType的原型,SubType的原型又指向SuperType的原型,继而在instance在调用getSuperValue()方法的时候,会顺着那条链从来往上找。

增加措施

在给SubType原型增多方法的时候,就算,父类上也许有雷同的名字,SubType将会覆盖那一个法子,达到重新的指标。 可是以此办法依然留存于父类中。

切记无法以字面量的花样丰盛,因为,上边说过通超过实际例承袭本质上便是重写,再使用字面量格局,又是一遍重写了,但此次重写未有跟父类有任何关系,所以就能产生原型链截断。

function SuperType() { this.property = true } SuperType.prototype.getSuperValue = function () { return this.property } function SubType() { this.subproperty = false } SubType.prototype = new SuperType() SubType.prototype = { getSubValue:function () { return this.subproperty } } var instance = new SubType() console.log(instance.getSuperValue()) // error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function SuperType() {
  this.property = true
}
SuperType.prototype.getSuperValue = function () {
  return this.property
}
function SubType() {
  this.subproperty = false
}
SubType.prototype = new SuperType()
SubType.prototype = {
  getSubValue:function () {
   return this.subproperty
  }
}
var instance = new SubType()
console.log(instance.getSuperValue())  // error

问题

偏偏的选取原型链承袭,首要难题根源包涵引用类型值的原型。

function SuperType() { this.colors = ['red', 'blue', 'green'] } function SubType() { } SubType.prototype = new SuperType() var instance1 = new SubType() var instance2 = new SubType() instance1.colors.push('black') console.log(instance1.colors) // ["red", "blue", "green", "black"] console.log(instance2.colors) // ["red", "blue", "green", "black"]

1
2
3
4
5
6
7
8
9
10
11
function SuperType() {
  this.colors = ['red', 'blue', 'green']
}
function SubType() {
}
SubType.prototype = new SuperType()
var instance1 = new SubType()
var instance2 = new SubType()
instance1.colors.push('black')
console.log(instance1.colors)  // ["red", "blue", "green", "black"]
console.log(instance2.colors) // ["red", "blue", "green", "black"]

在SuperType构造函数定义了二个colors属性,当SubType通过原型链承接后,那个天性就能油可是生SubType.prototype中,就跟特地成立了SubType.prototype.colors同样,所以会促成SubType的兼具实例都会共享这一个性子,所以instance1修改colors这些引用类型值,也会突显到instance第22中学。

原型链

借用构造函数

此办法为了消除原型中富含引用类型值所带来的标题。

这种艺术的构思正是在子类构造函数的内部调用父类构造函数,能够借助apply()和call()方法来改换目的的进行上下文

function SuperType() { this.colors = ['red', 'blue', 'green'] } function SubType() { // 继承SuperType SuperType.call(this) } var instance1 = new SubType() var instance2 = new SubType() instance1.colors.push('black') console.log(instance1.colors) // ["red", "blue", "green", "black"] console.log(instance2.colors) // ["red", "blue", "green"]

1
2
3
4
5
6
7
8
9
10
11
12
function SuperType() {
  this.colors = ['red', 'blue', 'green']
}
function SubType() {
  // 继承SuperType
  SuperType.call(this)
}
var instance1 = new SubType()
var instance2 = new SubType()
instance1.colors.push('black')
console.log(instance1.colors)  // ["red", "blue", "green", "black"]
console.log(instance2.colors) // ["red", "blue", "green"]

在新建SubType实例是调用了SuperType构造函数,这样来讲,就能够在新SubType指标上施行SuperType函数中定义的富有指标开始化代码。

结果,SubType的每种实例就能够怀有友好的colors属性的别本了。

传送参数

依傍构造函数还大概有一个优势正是能够传递参数

function SuperType(name) { this.name = name } function SubType() { // 继承SuperType SuperType.call(this, 'Jiang') this.job = 'student' } var instance = new SubType() console.log(instance.name) // Jiang console.log(instance.job) // student

1
2
3
4
5
6
7
8
9
10
11
12
function SuperType(name) {
  this.name = name
}
function SubType() {
  // 继承SuperType
  SuperType.call(this, 'Jiang')
 
  this.job = 'student'
}
var instance = new SubType()
console.log(instance.name)  // Jiang
console.log(instance.job)   // student

问题

万两唯有依靠构造函数,方法都在构造函数中定义,由此函数无法达到规定的标准复用

率先得要驾驭怎么是原型链,在一篇作品看懂proto和prototype的关系及界别中讲得老大详尽

结缘承继(原型链 构造函数)

结合承袭是将原型链承袭和构造函数结合起来,从而发挥两岸之长的一种情势。

思路便是行使原型链完毕对原型属性和措施的接续,而透过借用构造函数来促成对实例属性的持续。

这么,既通过在原型上定义方法落成了函数复用,又能够确定保证每一个实例都有它自个儿的性质。

function SuperType(name) { this.name = name this.colors = ['red', 'blue', 'green'] } SuperType.prototype.sayName = function () { console.log(this.name) } function SubType(name, job) { // 承袭属性 SuperType.call(this, name) this.job = job } // 继承方法 SubType.prototype = new SuperType() SubType.prototype.constructor = SuperType SubType.prototype.sayJob = function() { console.log(this.job) } var instance1 = new SubType('Jiang', 'student') instance1.colors.push('black') console.log(instance1.colors) //["red", "blue", "green", "black"] instance1.sayName() // 'Jiang' instance1.sayJob() // 'student' var instance2 = new SubType('J', 'doctor') console.log(instance2.colors) // //["red", "blue", "green"] instance2.sayName() // 'J' instance2.sayJob() // 'doctor'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function SuperType(name) {
  this.name = name
  this.colors = ['red', 'blue', 'green']
}
SuperType.prototype.sayName = function () {
  console.log(this.name)
}
function SubType(name, job) {
  // 继承属性
  SuperType.call(this, name)
 
  this.job = job
}
// 继承方法
SubType.prototype = new SuperType()
SubType.prototype.constructor = SuperType
SubType.prototype.sayJob = function() {
  console.log(this.job)
}
var instance1 = new SubType('Jiang', 'student')
instance1.colors.push('black')
console.log(instance1.colors) //["red", "blue", "green", "black"]
instance1.sayName() // 'Jiang'
instance1.sayJob()  // 'student'
var instance2 = new SubType('J', 'doctor')
console.log(instance2.colors) // //["red", "blue", "green"]
instance2.sayName()  // 'J'
instance2.sayJob()  // 'doctor'

这种格局防止了原型链和构造函数承袭的老毛病,融入了她们的帮助和益处,是最常用的一种持续形式。

原型链承继基本思维正是让三个原型对象指向另二个品种的实例

原型式承继

信赖原型能够依照已部分对象创造新指标,同不时间还不必因而创制自定义类型。

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

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

在object函数内部,先创制贰个有时性的构造函数,然后将盛传的对象作为那几个构造函数的原型,最终回来这几个不常类型的二个新实例。

真相上来讲,object对传播当中的靶子试行了一回浅复制。

var person = { name: 'Jiang', friends: ['Shelby', 'Court'] } var anotherPerson = object(person) console.log(anotherPerson.friends) // ['Shelby', 'Court']

1
2
3
4
5
6
var person = {
  name: 'Jiang',
  friends: ['Shelby', 'Court']
}
var anotherPerson = object(person)
console.log(anotherPerson.friends)  // ['Shelby', 'Court']

这种方式要去你无法不有五个对象作为另三个对象的根基。

在这几个例子中,person作为另贰个对象的基本功,把person传入object中,该函数就能够回到八个新的靶子。

以此新对象将person作为原型,所以它的原型中就含有多少个中坚类型和二个引用类型。

于是意味着假如还会有此外贰个对象关系了person,anotherPerson修改数组friends的时候,也会浮未来那一个指标中。

Object.create()方法

ES5因此Object.create()方法标准了原型式传承,基本上能用多个参数,壹个是用作新对象原型的靶子和二个可选的为新目的定义额外属性的对象,行为等同,基本用法和方面包车型大巴object一样,除了object不能够承受第一个参数以外。

var person = { name: 'Jiang', friends: ['Shelby', 'Court'] } var anotherPerson = Object.create(person) console.log(anotherPerson.friends) // ['Shelby', 'Court']

1
2
3
4
5
6
var person = {
  name: 'Jiang',
  friends: ['Shelby', 'Court']
}
var anotherPerson = Object.create(person)
console.log(anotherPerson.friends)  // ['Shelby', 'Court']

function SuperType() {

寄生式承袭

寄生式承袭的思绪与寄生构造函数和工厂方式类似,即开立贰个仅用于封装传承进度的函数。

function createAnother(o) { var clone = Object.create(o) // 创造贰个新目的 clone.sayHi = function() { // 增多形式 console.log('hi') } return clone // 再次回到那个目的 } var person = { name: 'Jiang' } var anotherPeson = createAnother(person) anotherPeson.sayHi()

1
2
3
4
5
6
7
8
9
10
11
12
function createAnother(o) {
  var clone = Object.create(o) // 创建一个新对象
  clone.sayHi = function() { // 添加方法
    console.log('hi')
  }
  return clone  // 返回这个对象
}
var person = {
  name: 'Jiang'
}
var anotherPeson = createAnother(person)
anotherPeson.sayHi()

依据person再次来到了贰个新指标anotherPeson,新目的不仅仅全体了person的本性和章程,还恐怕有温馨的sayHi方法。

在关键思考对象而不是自定义类型和构造函数的情况下,那是三个卓有作用的格局。

  this.property = true

寄生组合式承接

在前边说的组成形式(原型链 构造函数)中,承袭的时候须要调用两次父类构造函数。

父类

function SuperType(name) { this.name = name this.colors = ['red', 'blue', 'green'] }

1
2
3
4
function SuperType(name) {
  this.name = name
  this.colors = ['red', 'blue', 'green']
}

先是次在子类构造函数中

function SubType(name, job) { // 承袭属性 SuperType.call(this, name) this.job = job }

1
2
3
4
5
6
function SubType(name, job) {
  // 继承属性
  SuperType.call(this, name)
 
  this.job = job
}

其次次将子类的原型指向父类的实例

// 承接方法 SubType.prototype = new SuperType()

1
2
// 继承方法
SubType.prototype = new SuperType()

当使用var instance = new SubType()的时候,会发出两组name和color属性,一组在SubType实例上,一组在SubType原型上,只不超过实际例上的遮掩了原型上的。

采取寄生式组合情势,能够规避这一个难点。

这种方式通过借用构造函数来继续属性,通过原型链的混成格局来一而再方法。

基本思路:不必为了钦点子类型的原型而调用父类的构造函数,大家需求的仅仅正是父类原型的八个别本。

实为上正是采取寄生式承袭来持续父类的原型,在将结果钦定给子类型的原型。

function inheritPrototype(subType, superType) { var prototype = Object.create(superType.prototype) prototype.constructor = subType subType.prototype = prototype }

1
2
3
4
5
function inheritPrototype(subType, superType) {
  var prototype = Object.create(superType.prototype)
  prototype.constructor = subType
  subType.prototype = prototype
}

该函数完成了寄生组合承继的最简易款式。

本条函数接受四个参数,贰个子类,一个父类。

第一步成立父类原型的别本,第二步将创建的别本增添constructor属性,第三部将子类的原型指向那么些别本。

function SuperType(name) { this.name = name this.colors = ['red', 'blue', 'green'] } SuperType.prototype.sayName = function () { console.log(this.name) } function SubType(name, job) { // 承继属性 SuperType.call(this, name) this.job = job } // 承继inheritPrototype(SubType, SuperType) var instance = new SubType('Jiang', 'student') instance.sayName()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function SuperType(name) {
  this.name = name
  this.colors = ['red', 'blue', 'green']
}
SuperType.prototype.sayName = function () {
  console.log(this.name)
}
function SubType(name, job) {
  // 继承属性
  SuperType.call(this, name)
 
  this.job = job
}
// 继承
inheritPrototype(SubType, SuperType)
var instance = new SubType('Jiang', 'student')
instance.sayName()

填补:直接利用Object.create来贯彻,其实便是将上边封装的函数拆开,那样演示能够更便于通晓。

function SuperType(name) { this.name = name this.colors = ['red', 'blue', 'green'] } SuperType.prototype.sayName = function () { console.log(this.name) } function SubType(name, job) { // 承袭属性 SuperType.call(this, name) this.job = job } // 承继 SubType.prototype = Object.create(SuperType.prototype) // 修复constructor SubType.prototype.constructor = SubType var instance = new SubType('Jiang', 'student') instance.sayName()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function SuperType(name) {
  this.name = name
  this.colors = ['red', 'blue', 'green']
}
SuperType.prototype.sayName = function () {
  console.log(this.name)
}
function SubType(name, job) {
  // 继承属性
  SuperType.call(this, name)
 
  this.job = job
}
// 继承
SubType.prototype = Object.create(SuperType.prototype)
// 修复constructor
SubType.prototype.constructor = SubType
var instance = new SubType('Jiang', 'student')
instance.sayName()

ES6新扩大了二个艺术,Object.setPrototypeOf,能够直接创制关联,而且并非手动增添constructor属性。

// 继承 Object.setPrototypeOf(SubType.prototype, SuperType.prototype) console.log(SubType.prototype.constructor === SubType) // true

1
2
3
// 继承
Object.setPrototypeOf(SubType.prototype, SuperType.prototype)
console.log(SubType.prototype.constructor === SubType) // true

1 赞 2 收藏 评论

新京葡娱乐场网址 1

}

SuperType.prototype.getSuperValue = function () {

  return this.property

}

function SubType() {

  this.subproperty = false

}

SubType.prototype = new SuperType()

SubType.prototype.getSubValue = function () {

  return this.subproperty

}

var instance = new SubType()

console.log(instance.getSuperValue()) // true

代码定义了四个门类SuperType和SubType,每一种门类分别有壹本性格和叁个方法,SubType继承了SuperType,而继续是因此创办SuperType的实例,并将该实例赋给SubType.prototype完成的。

达成的原形是重写原型对象,代之以五个新品类的实例,那么存在SuperType的实例中的全体属性和章程,今后也存在于SubType.prototype中了。

咱俩领会,在创制多个实例的时候,实例对象中会有一个里边指针指向创设它的原型,实行关联起来,在那边代码SubType.prototype = new SuperType(),也会在SubType.prototype制造一个之中指针,将SubType.prototype与SuperType关联起来。

故而instance指向SubType的原型,SubType的原型又指向SuperType的原型,继而在instance在调用getSuperValue()方法的时候,会沿着这条链一直往上找。

丰硕办法

在给SubType原型增加方法的时候,假如,父类上也是有一样的名字,SubType将会覆盖那个措施,到达重新的指标。 不过以此艺术还是存在于父类中。

切记不能够以字面量的花样丰裕,因为,下面说过通超过实际例承继本质上正是重写,再使用字面量方式,又是一遍重写了,但这一次重写未有跟父类有任何关系,所以就能够形成原型链截断。

function SuperType() {

  this.property = true

}

SuperType.prototype.getSuperValue = function () {

  return this.property

}

function SubType() {

  this.subproperty = false

}

SubType.prototype = new SuperType()

SubType.prototype = {

  getSubValue:function () {

  return this.subproperty

  }

}

var instance = new SubType()

console.log(instance.getSuperValue())  // error

问题

独自的采取原型链承继,主要难题根源包含引用类型值的原型。

function SuperType() {

  this.colors = ['red', 'blue', 'green']

}

function SubType() {

}

SubType.prototype = new SuperType()

var instance1 = new SubType()

var instance2 = new SubType()

instance1.colors.push('black')

console.log(instance1.colors)  // ["red", "blue", "green", "black"]

console.log(instance2.colors) // ["red", "blue", "green", "black"]

在SuperType构造函数定义了一个colors属性,当SubType通过原型链继承后,那些本性就能冒出SubType.prototype中,就跟特意成立了SubType.prototype.colors一样,所以会促成SubType的兼具实例都会共享那脾特性,所以instance1修改colors这一个引用类型值,也会展示到instance第22中学。

借用构造函数

此办法为了化解原型中含有引用类型值所带动的题目。

这种格局的思辨正是在子类构造函数的里边调用父类构造函数,能够借助apply()和call()方法来改换指标的实施上下文

function SuperType() {

  this.colors = ['red', 'blue', 'green']

}

function SubType() {

  // 继承SuperType

  SuperType.call(this)

}

var instance1 = new SubType()

var instance2 = new SubType()

instance1.colors.push('black')

console.log(instance1.colors)  // ["red", "blue", "green", "black"]

console.log(instance2.colors) // ["red", "blue", "green"]

在新建SubType实例是调用了SuperType构造函数,那样来讲,就能在新SubType目的上举行SuperType函数中定义的富有目的早先化代码。

结果,SubType的各类实例就集会场全体友好的colors属性的别本了。

传送参数

依傍构造函数还会有四个优势便是足以传递参数

function SuperType(name) {

  this.name = name

}

function SubType() {

  // 继承SuperType

  SuperType.call(this, 'Jiang')

  this.job = 'student'

}

var instance = new SubType()

console.log(instance.name)  // Jiang

console.log(instance.job)  // student

问题

只要单纯依赖构造函数,方法都在构造函数中定义,因而函数不可能完毕复用

组合承继(原型链 构造函数)

结缘承接是将原型链承接和构造函数结合起来,从而发挥双方之长的一种方式。

思路正是利用原型链达成对原型属性和艺术的承继,而通过借用构造函数来完成对实例属性的持续。

如此,既通过在原型上定义方法达成了函数复用,又能够确定保障各个实例都有它和睦的性质。

function SuperType(name) {

  this.name = name

  this.colors = ['red', 'blue', 'green']

}

SuperType.prototype.sayName = function () {

  console.log(this.name)

}

function SubType(name, job) {

  // 承接属性

  SuperType.call(this, name)

  this.job = job

}

// 承袭方法

SubType.prototype = new SuperType()

SubType.prototype.constructor = SuperType

SubType.prototype.sayJob = function() {

  console.log(this.job)

}

var instance1 = new SubType('Jiang', 'student')

instance1.colors.push('black')

console.log(instance1.colors) //["red", "blue", "green", "black"]

instance1.sayName() // 'Jiang'

instance1.sayJob()  // 'student'

本文由67677新澳门手机版发布于新京葡娱乐场网址,转载请注明出处:新京葡娱乐场网址:JS的六种继承方式,六种继承

关键词: