365bet亚洲版登录-bet官网365入口

365bet亚洲版登录拥有超过百间客房,bet官网365入口的文化历经几十年的传承和积淀形成的核心内容获得业界广泛的认可,365bet亚洲版登录是目前信誉最高的娱乐场所,同国内外几百家网上内容供应商建立了合作关系。

六种继承方式

JavaScript 多种持续方式

2017/06/20 · JavaScript · 继承

初稿出处: Xuthus Blog   

接轨是面向对象编制程序中又一相当首要的定义,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

问题

比方单纯依据构造函数,方法都在构造函数中定义,由此函数不能够达到规定的规范复用

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

重组承继是将原型链继承和构造函数结合起来,进而发挥双方之长的一种形式。

思路便是运用原型链达成对原型属性和章程的后续,而经过借用构造函数来落到实处对实例属性的接轨。

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

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不可能接受第3个参数以外。

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 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方法。

在显要缅想对象实际不是自定义类型和构造函数的事态下,那是叁个实用的方式。

寄生组合式承袭

在前头说的组合格局(原型链+构造函数)中,承继的时候须要调用五回父类构造函数。

父类

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

本文由365bet亚洲版登录发布于 Web前端,转载请注明出处:六种继承方式

您可能还会对下面的文章感兴趣: