mx52jing/blog

继承

Opened this issue · 0 comments

new 过程中做了什么事情

创建新对象
var obj = new Object()

设置原型链
obj._proto_ = Object.prototype

执行构造函数并且绑定this为实例对象
var result = Object.call(obj)

返回实例对象(确保返回一个对象)
return typeof result == 'object' ? result : obj

构造函数,原型、实例

每个构造函数都会有一个原型对象,原型对象上又会有一个指针指向构造函数,实例包含一个指向原型的指针

2027128666

    function Foo(){}
    var foo = new Foo()
    foo.__proto__ = Foo.prototype

原型链继承

function Foo(){
  this.name = "西游记";
  this.book = ["三国演义", "水浒传"]
}
Foo.prototype.like = "金箍棒"
Foo.prototype.getName = function(){
  return this.name
}

function Bar(){
  this.age = 12
}
Bar.prototype = new Foo() // 继承Foo

Bar.prototype.getAge = function(){
  return this.age
}

let baz = new Bar()
let baz1 = new Bar()


console.log(baz.getName()) // 西游记
console.log(baz.like) // "金箍棒"

原型链继承会导致修改某个实例的值会影响到其他实例,因为包含引用类型的原型属性会被所有实例共享

baz.book   //  ["三国演义", "水浒传"]
baz1.book // ["三国演义", "水浒传"]
baz.book.push("西游记")
baz.book  // ["三国演义", "水浒传", "西游记"]
baz1.book  // ["三国演义", "水浒传", "西游记"]

修改baz.book结果影响了baz1.book,并不符合初衷

原型链继承优点:
很简便的实现多重继承

原型链继承缺点:
1、创建子实例时无法向父实例传递参数
2、所有实例共享原型,修改其中一个会影响其他
3、不能使用对象字面量形式,会切断对象和原型之间的联系(会修改constructor)

构造函数继承

function Foo(name, age) {
  this.name = name;
  this.age = age;
}

function Baz(){
 Foo.call(this, "张三", 12)
 this.like = "哈哈"
}
Baz.prototype.sayName = function(){
  return this.name
}

let baz = new Baz()
baz.name // 张三
baz.sayName() //张三
baz.like // 哈哈

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

function Foo(name, age) {
  this.name = name
  this.age = age
  this.book = ["水浒传","西游记"]
}
Foo.prototype.sayHello = function(){
  return 'hello'
}

function Bar(){
  Foo.call(this, "武松", 88) // 构造函数继承
}
Bar.prototype = new Foo() // 原型链模式继承
Bar.prototype.sayName = function(){
  return this.name
}


let bar = new Bar()
let bar1 = new Bar()

bar.book // ["水浒传", "西游记"]
bar1.book //["水浒传", "西游记"]
bar.book.push('阿甘正传')

bar.book // ["水浒传", "西游记", "阿甘正传"]

bar1.book // ["水浒传", "西游记"]

组合继承是常用的继承模式

将原型用对象字面量的形式定义之后,会切断构造函数和原型之间的联系,构造函数会指向一个新的原型(也修改了原型中constructor的值)

function Foo(){}

Foo.prototype.name = 'foo'
Foo.prototype.getName = function(){
  return this.name
}


let foo = new Foo()

console.log(foo.getName()) // foo

Foo.prototype = {  // 重写了原型对象
  name: 'anotherFoo',
  age: 12,
  getAge: function(){
    return this.age
  },
  getAnotherName: function(){
     return this.name
  }
}

let bar = new Foo()

console.log(bar.getAge()) // 12

console.log(bar.getName())  // error 报错,因为没有继承到这个函数
console.log(bar.getAnotherName()) // anotherFoo