js- 原型与原型链的继承

原型链作为js语言中的重点、难点内容,并且也是面试官常问的一个内容,理解原型链并掌握它对我们以后找工作时大有裨益,那么下面让我们来了解原型链这个内容。

原型链的概念

每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,实例包含一个指向原型对象的内部指针,如果我们让原型对象等于另一个类型的实例,则此时的原型对象包含指向另一个类型的指针,如此层层递进构成原型链。
相当于:
构造函数使用new操作符创建实例对象,构造函数里面有个prototype属性指向原型对象,实例对象里面又有一个_ proto _属性指向原型对象,当然原型对象里面有constructor属性指向构造函数,层层递进。
好了,如果有人还不理解这个概念的话,我们用一张图来说明这个问题:
原型链的概念

原型链的搜索属性过程

function SuperType(){
        this.property = true;
    }
    SuperType.prototype.getSuperValue =function (){
        return this.property;
    };
    function SubType(){
        this.subproperty = false;
    }
    //继承SuperType
    SubType.prototype =new SuperType();
    SubType.prototype.getSubValue = function (){
        return this.subproperty;
    };
    var instance = new SubType();
    console.log(instance.getSuperValue());

当然在浏览器的控制台结果为true,这究竟为何?
一组图片来解释下其中的缘由:
原型链的继承
其中查找的流程一般如下所示:
在当前实例对象obj中,查找obj的属性或方法,找到后返回
没有找到,通过obj. _ proto _,找到obj构造函数的prototype并且查找上面的属性和方法,找到后返回,没有找到,把Array.prototype当做obj,重复以上步骤
原型链是有终点的,最后查找到Object.prototype时,Object.prototype._ proto _ === null,意味着查找结束。

hasOwnProperty:

hasOwnProperty()方法可以检测一个属性存在于实例中还是原型中,这个方法只在给定属性存在于对象实例中才返回true;
在原型链上查询属性是比较耗时,对性能又有影响,试图访问不存在的属性时会遍历整个原型链,造成了不必要的资源浪费。遍历对象属性时,每个可枚举的属性都会被枚举出来。 要检查是否具有自己定义的属性,而不是原型链上的属性,必须使用hasOwnProperty方法。

function Person(){
    }
    Person.prototype.name = "Tom";
    Person.prototype.age = 19;
    Person.prototype.job = "Teacher";
    var person1 = new Person();
    person1.name = "Jack";
    console.log(person1.hasOwnProperty("name"));
    console.log(person1.hasOwnProperty("age"));

结果
注:hasOwnProperty 是 JavaScript 中唯一处理属性并且不会遍历原型链的方法。

原型链的继承

js主要是通过原型链来实现继承的,继承的方式多种多样,但就其实用性而言,我们用的最多的还是组合使用构造函数和原型模式。
即:构造函数模式用于定义实例化属性,原型模式用于定义方法和共享的属性

function Person(name,age){
        this.name = name;
        this.age =age;
        this.friend = ["213", "456"];
    }
    Person.prototype = {
        constructor : Person,
        sayName : function (){
            console.log(this.name);
        }
    }
    var person1 = new Person("yf", 20);
    var person2 = new Person("lrt", 19);
    person1.friend.push("789");
    console.log(person1.friend);
    console.log(person2.friend);

继承结果
在这份代码里面,充分的体现了这种方式继承的好处。还有里面的person2.friend之所以没有改变,是因为person1,person2保存的都是friend的副本,所以person2.friend的值是没有改变的。

Tips

1、原型对象修改(通过构造函数方式来修改)的变动都可以从实例上反映出来。
2、重写原型对象,会切断构造函数和最初原型之间的联系,实例指针仅指向原型函数,而不指向构造函数。
3、省略了构造函数传递初始化参数,导致所有实例在默认情况下都取得相同的属性值。
4、实例化的对象无法修改原型的固有属性,引用类型可以。
5、子类型有时需要覆盖超类型中的某个方法,给原型添加方法的代码一定要放在替换原型的语句之后
6、不能在原型链实现继承后,使用对象字面量的方法来添加新方法,否则将会导致 继承失败。

好了,以上就是自己对原型链的一些理解,如果小伙伴们有不同的想法,欢迎来一起讨论,一起进步。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值