Javascript 中实现对象原型继承的三种方式

Javacript 中有一个思想:万物皆对象,几个基础类型(String, Number, Boolean, Null, Undefined, Symbol),几个引用类型(Array, Date, Function, Object, Regexp)本质上都是对象。es6

那么对象之间如何实现关联(也就是OO里面的继承)呢?js中经过prototype(原型)来实现。每一个对象都有一个__proto__指针,指向上一个原型,这就像是一个链表。最顶端的object的原型指向null, 表明终结。 因此,当咱们定义一个变量:浏览器

let name = new String('allen')
//let name = 'allen'
console.log('name:', name)
console.log('name.__proto__:', name.__proto__)
console.log('name.__proto__.__proto__:',name.__proto__.__proto__)	
console.log('name.__proto__.__proto__.__proto__:', name.__proto__.__proto__.__proto__)
复制代码

输出:bash

name: [String: 'allen']
name.__proto__: [String: '']
name.__proto__.__proto__: {}
name.__proto__.__proto__.__proto__: null
[Finished in 0.1s]
复制代码

咱们要实现继承(至少看上去是继承的样子)有三种方法:函数

  1. Object.create(),
  2. Function.prototype={},
  3. class extend

1. Object.create()

看例子:ui

let dog = {
	name: 'dog'
	}
	
let mardDog = Object.create(dog)
复制代码

这里 mardDog 是一个新的空对象,存有一个指针__proto__,指向的是 dog 对象, dog对象中也有一个__proto__,指向的是ObjectObject中也有一个__proto__,指向的是null。 这就是原型链。利用Object.create(),咱们能够建立多个对象,dog对象都是他们的原型,那么他们可不能够改变dog里面的属性呢。答案是能够 的,但不建议。代码以下:this

mardDog.name = 'mardDog'

/*
dog ====> {name: 'dog'}
mardDog ====> {name: 'mardDog'}
*/
复制代码

能够看到,咱们并无能改变原型中的属性。而下面这种方式:spa

mardDog.__proto__.name = 'xxxDog'

/*
	dog ====> {name: 'xxxDog'}
	mardDog ====> {name: 'mardDog'}
*/
复制代码

咱们成功改变了上一层的属性。 那么,为何咱们不推荐使用__proto__去改变原型中的共有属性呢?由于这种方法很是慢,而且会严重影响进程。事实上,__proto__历来没有被写进规范,可是浏览器厂商都实现了它。prototype

2. Function.prototype = {}

这个方法实际上是利用构造函数来实现 先看例子:指针

function dog (){
	this.name = 'dog'
	this.age = 1
}

let dog1 = new dog()

function mardDog (){
	this.yiel = function (){
		console.log(this.name)
	}
}

mardDog.prototype = new dog()

let mardDog1 = new mardDog()
mardDog1.yiel()
复制代码

输出:code

dog
[Finished in 0.1s]
复制代码

能够看到,咱们成功实现了mardDog 对 dog的继承

3. class extend

es6中实现了 class 这个关键字,虽然只是语法糖,本质上是方法二的封装,但这种思路对熟悉OO的开发者是很友好的,而且把js中使人迷惑的原型封装了起来,使它变得更容易开发。

例子:

class dog {
   constructor () {
   	this.name = 'dog'
   	this.age = 1
   }
}

class mardDog extends dog {
	constructor () {
		super()
	}
	yiel () {
		console.log(this.name)
	}
}
let mardDog1 = new mardDog()
mardDog1.yiel()
复制代码

输出:

dog
复制代码

这样咱们成功地实现了继承

总结

因为es6 是大势所趋,建议在工程环境中使用clas来实现对象的继承。固然原型以及原型链的原理是必须掌握的。es6中还有一些方法也是十分有用。如下:

Object.getPrototypeOf(childobj) 顾名思义,该方法获得childobj的prototype,也能够理解为父类。


Object.setPrototypeOf(childObj, obj)这个方法是将childObj设为obj的继承类。因为前面提到过,对prototype的操做十分微妙,因此这个方法仍是能不用就不用,能够用Object.create(obj)来代替


其余方法参照MDN上的解释

相关文章
相关标签/搜索