function Person (name,age,language){this.name = name;this.age = age;this.language = language;this.sleep = function (){console.log('im '+this.name+' im sleeping')}}Person.prototype.speak = function(){console.log('im '+this.name+' im speak '+this.language)}Person.prototype.eyes = 4
原型链继承
原理
将父类的实例作为子类的原型
子类.prototype = new 父类()
function Chinese(province){this.province = provincethis.eat = function(){console.log('im '+this.language+',im eating')}}Chinese.prototype = new Person()Chinese.prototype.constructor = Chinese //修复constructor的指向//如果有 prototype 上的方法和属性,要放在这里之后Chinese.prototype.language = 'chinese'
let gromy = new Chinese('吉林')
看下gromy都有什么?

gromy.speak()VM5382:2 im undefined im speak chinesegromy.sleep()VM5278:6 im undefined im sleepinggromy.eat()VM6138:4 im chinese,im eating
所以子类的实例可以使用父类的方法,但是由于无法向父类传参数,所以 没有name
优点
- 实现简单
-
缺点
不能向父类的构造函数传参
-
使用
构造函数继承
原理
在子类构造函数中通过 call 将父类的构造器中的内容合并
function Chinese(name,age,language,province){this.province = provincePerson.call(this,name,age,language)this.eat = function(){console.log('im '+this.language+',im eating')}}Chinese.prototype.language = 'chinese'
let gromy = new Chinese('gromy',18,'english')

属性,方法都合并过来了gromy.sleep()VM5659:6 im gromy im sleepinggromy.speak()VM5935:1 Uncaught TypeError: gromy.speak is not a functionat <anonymous>:1:7gromy.eat()VM6178:5 im english,im eating
优点
可以实现多继承(使用多个call)
- 可向父类传参(实际是把属性在构造器中合并过来了)
缺点
- 因为是合并过来的,所以每个子类的实例都是副本,影响性能
-
使用
原型+构造器组合
function Chinese(name,age,language,province){this.province = provincePerson.call(this,name,age,language)this.eat = function(){console.log('im '+this.language+',im eating')}}Chinese.prototype = new Person()Chinese.prototype.constructor = Chinese //修复constructor的指向//如果有 prototype 上的方法和属性,要放在这里之后Chinese.prototype.language = 'chinese'
let gromy = new Chinese('gromy',18,'chinese','吉林')

gromy.sleep()VM6305:6 im gromy im sleepinggromy.speak()VM6305:10 im gromy im speak chinesegromy.eat()VM6307:5 im chinese,im eatinggromy.eyes4
优点
可以继承所有父类的属性和方法
- 可传参数
缺点
- 部分可实现多继承(call的部分)
-
原型+构造器优化
组合的最大弊端是调用了两次父类的构造器,两次实例化
function Chinese(name,age,language,province){this.province = provincePerson.call(this,name,age,language)this.eat = function(){console.log('im '+this.language+',im eating')}}Chinese.prototype = Person.prototype//Chinese.prototype.constructor = ChineseChinese.prototype.language = 'chinese'
let gromy = new Chinese('gromy',18,'chinese','吉林')

gromy.sleep()VM6422:6 im gromy im sleepinggromy.speak()VM6422:10 im gromy im speak chinesegromy.eat()VM6424:5 im chinese,im eatinggromy.eyes4
优点
继承了所有父类的属性和方法
-
缺点
由于子类直接被赋值了父类的prototype,所以子类的实例的 proto 指向了父类
原型+构造器优化(使用Object.assign())
Object.assign() 是使用现有的对象来提供新创建的对象的 会将原型作用在实例的 proto 上
function Chinese(name,age,language,province){this.province = provincePerson.call(this,name,age,language)this.eat = function(){console.log('im '+this.language+',im eating')}}Chinese.prototype = Object.assign(Person.prototype) //核心Chinese.prototype.constructor = Chinese //核心Chinese.prototype.language = 'chinese'
gromy.__proto__

gromy.proto === Chinese.prototype
优点
-
缺点
-
es6的class
class Person {constructor(name,age,language){this.name = name;this.age = age;this.language = language;this.sleep = function(){console.log('im '+this.name+' im sleeping')}}speak(){console.log('im '+this.name+' im speak '+this.language)}}
class Chinese extends Person{constructor(name,age,language,province){super(name,age,language)this.province = provincethis.eat = function(){console.log('im '+this.language+',im eating')}}}
let gromy = new Chinese('gromy',18,'chinese','吉林')

gromy.sleep()VM6422:6 im gromy im sleepinggromy.speak()VM6422:10 im gromy im speak chinesegromy.eat()VM6424:5 im chinese,im eatinggromy.eyes4
优点
-
缺点
浏览器对支持es6有限制

