js对象继承

1. 基本概念

实例对象: 通过实例的方式(new)构造出来的对象
原型对象:所有实例的公共祖先,在实例对象上可以得到原型对象的属性和方法
构造函数:可以通过new关键子执行的函数

//Foo是一个构造函数
function Foo(){
     this.a = '1'
  }
//foo 是通过new构造的一个实例对象
var foo = new Foo()

2. prototype 、proto 、constructor之间的关系

prototype即原型,原型的访问方式有
(1)通过构造函数的方式 Foo.prototype,该方法适合修改原型
(2)通过实例的方式 foo.proto
(3)ES6方式 Object.getprototypeOf(foo)

function Foo(){
        this.a = 1
  }
 //原型的重写
 Foo.prototype = {   //这是构造函数的原型
       aa: 10,
       bb: function(){
       console.log(20);
        }
  }
var foo = new Foo();  //这是一个实例对象
console.log(foo.aa);  //10 ,实例对象可以拿到原型的属性
console.log(foo.a);   //1
console.log(foo);
console.log(foo.__proto__);  //获得其原型对象{aa: 10, bb: ƒ}

constructor 是原型上的一个属性,它指向的是构造函数本身

//例如
function Foo(){
    this.a = 1
}
var foo = new Foo();  //这是一个实例对象
console.log(foo.__proto__);  //获得该实例的原型队形

输出结果:
{constructor: ƒ}

console.log(Foo.prototype.constructor === Foo); //true
一旦更改原型,constructor改变

//重写原型
 Foo.prototype = {   //这是构造函数的原型
            aa: 10,
            bb: function(){
                console.log(20);
            }
        }
var foo = new Foo();  //这是一个实例
console.log(Foo.prototype.constructor);

输出
ƒ Object()
原型链为:
在这里插入图片描述
Foo 是本身没有constructor属性 ——(父亲)原型 Prototype,依旧没有constructor属性 —— 爷爷prototype constructot 属性值是Object
console.log(Foo.prototype.constructor);
根据原型链搜索
Foo重写后没有 constructor 然后找它的父亲,仍然没有constructor ,再找他爷爷,找到了,原型链继承得到。

注意:
当重写原型时,为其加上constructor属性,指向这个构造函数

 Foo.prototype = {   //这是构造函数的原型
            aa: 10,
            bb: function(){
                console.log(20);
            }
            constructor: Foo
        }

总结:
prototype和__proto__都是指向的原型,只是访问方法不同
constructot 指向的时构造函数

3. 对象的继承

  1. 原型链继承

    根据原型链继承——实例对象可以拿到原型对象的属性和方法——也能拿到原型的原型的属性和方法,一级级继承得到。

<script>
        function Super() {
            this.a = '1'

            }
        Super.prototype.say = function(){
            console.log(222);
        }
        function Sub(){
        }
        //Sub的原型是一个Super实例,所以Sub.prototype本身具有了属性a,同时可以访问其原型Super.prototype的方法
        Sub.prototype = new Super();

        var sub1 = new Sub();  //它具有原型
        console.log(sub1.a);
        console.log(sub1.say);

    </script>

解释:(—>表示原型是)
实例对象sub1—>Sub.prototype(只是一个new super实例对象,所以可以拿到实例上的属性),并且通过Super.prototypy可以访问Super 的原型对象方法

出现问题:
引用值(String,Object类型)共享问题)

 function Super() {
     this.a = [1,2,3]
}

//在sub1.a的属性值中加入新的数
 sub1.a.push(4)
console.log(sup.a); //[1, 2, 3]
console.log(sub1.a);  //[1, 2, 3, 4]
console.log(sub2.a);  //[1, 2, 3, 4]
  1. 构造函数继承——解决引用值的共享问题

此继承存在的问题:没办法拿到原型上的方法

<script>
        function Super() {
            this.a = [1, 2, 3]
            }
        Super.prototype.say = function () {
                console.log(222);
            }
        function Sub() {
            Super.call(this);  //这里的this指向创建的Sub对象
            }
            
            //实现互不影响
        var sub1 = new Sub();
        // 执行过程,sub1为一个实例对象,在Sub构造函数中,this指向这个对象,
        // 执行Super.call(this) === Super(sub1) 到函数(此处没有和new 搭配使用
        //  ,其实是个普通函数吧,所有没发拿到原型上的方法)内执行 this.a === sub1.a
        var sub2 = new Sub();
          // 执行过程,sub2为一个实例对象,在Sub构造函数中,this指向这个对象,
        // 执行Super.call(this) === Super(sub2) 到函数内执行 this.a === sub2.a
    </script>
  1. 组合继承的方式(原型链与构造数组的结合)又叫伪经典继承
    组合其优点
    (1) 解决引用值的共享问题
    (2) 解决原型方法和属性调用问题
<script>
        function Super() {
            this.a = [1, 2, 3]
        }
        Super.prototype.say = function () {
            console.log(222);
        }

        function Sub() {
            Super.call(this);  //这里的this指向创建的Sub对象
        }

        // 新增——原型链关键语句
        Sub.prototype = new Super();
        //每次创建Sub实例对象,都会调用两次Super函数
        var sub1 = new Sub();
        var sub2 = new Sub();
</script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值