关于原型,原型链,继承的几种方法

创建对象的几种方式:

//字面量
var a = {name:'zhangsan'}
var b = new Object({name:'lisi'})
//构造函数
var M = function(name){
    this.name = name
}
var c = new M('wangwu)

//Object对象创建
var d = {name:'xiaoliu'}
var e = Object.create(d)

 

有上图可以看出构造函数new 出来的实例对象,有一个__proto__的指针。指向构造函数的原型对象。然后与构造函数的原型对象发生链条关系,就出现了原型链。下面我们打印出来如下的关系:

也就是说M new出来的实例对象--->M构造函数的prototype原型对象。M构造函数的原型对象中有constructor构造器,这个属性指向构造函数自己本身。

c instanceof M     //  true     用instanceof来检测c 是不是构造函数New 出来的实例对象。

 

下面就几种继承的方式,比较一下优缺点。

1,通过构造函数的方式继承

 function Father(){
            this.name = 'zhangsan'
        }
        Father.prototype.say = function(){
            console.log('我是father的原型方法')
        }
        function Son(){
            Father.call(this)
            this.age = 18
        }
        var a = new Son()
        var b = new Father()
         console.log(b.say)       // function(){console.log('我是father的原型方法')}
        console.log(a)          // Son   {name:'zhangsan',age:18} 
        console.log(a.say)    //undefiend

有call继承Father的实例对象。

缺点就是:无法继承原型下的属性或者方法。

2.通过原型链继承


        function Father() { 
            this.name = 'zhangsan'
            this.arr = [1,2,3]
         }
         function Son(){
             this.age = 18;
         }
         Son.prototype = new Father()
         console.log(new Son)   
         var a = new Son()
         var b = new Son()
         a.arr.push(4)
         console.log(a.arr)   //[1,2,3,4]
         console.log(b.arr)  //[1,2,3,4]

有上面代码看出,通过此种方法实现继承是有缺点的,
实例化两个Son 的实例对象,如果在父类中有引用类型的属性,会被共享,意思就是一个改动,全部改动。

3,组合继承

  //3混合继承
        function Father() { 
            this.name = 'zhangsan'
            this.arr = [1,2,3]
        }
        function Son(){
            Father.call(this)
            this.age = 18
        }
        Son.prototype = new Father()
        var a =new Son()
        var b =new Son()
        a.arr.push(4)
        console.log(a.arr,b.arr)    //[1,2,3,4]  [1,2,3]
     //虽然通过这种方式继承解决了被共享的问题,但是出现了下面的问题。在实例化Son时候,调用了父级的构造函数2次。

4,组合继承的另外一种写法

 

function Father() { 
            this.name = 'zhangsan'
            this.arr = [1,2,3]
        }
        function Son(){
            Father.call(this)
            this.age = 18
        }
        Son.prototype = Father.prototype
        var a =new Son()
        var b =new Son()
        a.arr.push(4) 
        console.log(a.arr,b.arr)   //[1,2,3,4]  [1,2,3]
这样写虽然解决了调用父级构造函数两次的问题,但是有这样的一个问题,就是子元素new 出来的是实例对象的 指向不明确,不知道是父级里的还是子元素里面的。

5 最优的继承方法

function Father() { 
            this.name = 'zhangsan'
            this.arr = [1,2,3]
        }
        function Son(){
            Father.call(this)
            this.age = 18
        }
        Son.prototype = Object.create(Father.prototype)
        Son.prototype.constructor = Son 
        var a =new Son()
        var b =new Son()
        a.arr.push(4) 
        console.log(a.arr,b.arr)   //[1,2,3,4]  [1,2,3]
解决了子元素的实例对象的constructor 指向不明的问题。

以上就是个人对原型,原型链,继承的理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值