原型与原型链

87 阅读1分钟

每个构造函数都有一个原型对象,原型对象又包含有个指向构造函数的指针,而实例则包含一个原型对象的指针(内存空间是共享的,当一个发生变化的时候,另一个也随之变化,构造函数的指向也发生变化)

image.png

1.原型链继承

每个构造函数都有一个原型对象,原型对象又包含有个指向构造函数的指针,而实例则包含一个原型对象的指针(内存空间是共享的,当一个发生变化的时候,另一个也随之变化,构造函数的指向也发生变化)

function Parent1(){
    this.name = 'parent1'
    this.play = [1,2,3]
}
function Child1(){
    this.type = 'child2'
}
Child1.prototype = new Parent1()
console.log(new Child1())
var s1 = new Child1()
var s2 = new Child1()
s1.play.push(4)
console.log(s1.play,s2.play) // [1,2,3,4] [1,2,3,4]

2.构造函数继承 (借助call)

function Parent1(){
    this.name = 'parent1'
}
Parent1.prototype.getName = function(){
    return this.name
}
function Child1(){
    Parent1.call(this)
    this.type = 'child1'
}
let child = new Child1()
console.log(child) // {name:'parent1',type:'child1''}
console.log(child.getName()) //报错

3.组合继承

function Parent3(){
    this.name = 'parent3'
    this.play = [1,2,3]
}
Parent3.prototype.getName = function (){
    return this.name
}
function Child3(){
    Parent3.call(this)
    this.type = 'child3'
}
Child3.prototype = new Parent3()
Child3.prototype.constructor = Child3
var s3 = new Child3()
var s4 = new Child3()
s3.play.push(4)
console.log(s3.play,s4.play) // [1,2,3,4] [1,2,3]
console.log(s3.getName()) // parent3
console.log(s4.getName()) // parent3

4. 圣杯模式

function inherit(Target,Origin){
    function F(){}
    F.prototype = Origin.prototype
    Target.prototype = new F()
    Target.prototype.constuctor = Target
    Target.prototype.uber = Origin.prototype
}

//上面的函数可以这样写

var inherit = (function (){
    var F = function (){}
    return function(Target,Origin){
        F.prototype = Origin.prototype
        Target.prototype = new F()
        Target.prototype.constuctor = Target
        Target.prototype.uber = Origin.prototype
    }
}())

// 这样写,是利用闭包让F()私有化

function Father(){}
function Son(){}
inherit(Son,Father)
var son = new Son()
var father = new Father()

Object.create() 和 new的区别:

// new
function Parent(){
    this.name = 'parent'
    this.play = [1,2,3]
}
function Child(){
    this.type = 'child'
}

var parent = new Parent()
Child.prototype = parent
Child.prototype.constructor = Child
let child = new Child();

console.log(parent.constructor === child.constructor)

parent.constructor === child.constructor  // true 都指向Child


// Object.create()

function Parent(){
    this.name = 'parent'
    this.play = [1,2,3]
}
function Child(){
    this.type = 'child'
}

let parent = new Parent();
Child.prototype = Object.create(new Parent())

Child.prototype.constructor = Child

let child = new Child(); 

console.log(parent.constructor === child.constructor)// false

Object.create就是这种写法,也是Object.create的原生写法:

function Parent(){
    this.name = 'parent'
    this.play = [1,2,3]
}
function Child(){
    this.type = 'child'
}

let parent = new Parent();
Child.prototype = parent

var F = function() {} //

let f = new F(); //
F.prototype = Parent.prototype //这四行就是Object.create

Child.prototype = new F(); //

Child.prototype.constructor = Child; //

let child = new Child(); //

console.log(parent.constructor === child.constructor) // false 指向各自的构造函数