彻底理解JS的原型和原型链

一、前言

  在深入理解原型和原型链之前,我们首先要搞懂以下两点:

  • 对应名称

    prototype:   原型,每一个对象都会从原型上‘继承’属性

    __proto__:  原型链,并不是单一指某一个,而是一条__proto__连起来的链条,当js引擎查找对象属性时,先查找对象本身是否具有,如果没有就去原型链上查找

   function Person() {

    }
    Person.prototype.fun = function (){
        console.log('我是构造函数的方法')
    }
    var person = new Person();
    console.log(person.fun());  //我是构造函数的方法
  • 从属关系

    prototype  ——> 函数的一个属性:对象{}   (每个函数都有prototype属性) 

                               ——>定义函数时自动添加,默认指向一个空的Object的对象

    __proto_ _——>  对象Object的一个属性: 对象{}   (每个对象都有__proto__属性) 

                               ——>创建对象时自动添加,默认值为构造函数的prototype的属性值

 

二、理解__proto__和prototype的联系

  首先,我们来看一张图:

  从图片可以看出,通俗来讲,就是函数里面有个prototype属性指向原型对象,实例化对象里面有个__proto__属性也指向原型对象,且与构造函数的原型对象是同一个,然后原型对象里面有个constructor属性指向的是构造函数。

function Person() {

    }
var person = new Person();
console.log(person.__proto__ === Person.prototype); //true
console.log(Person === Person.prototype.constructor);//true

  补充说明,当获取 person.constructor 时,其实 person 中并没有 constructor 属性,当不能读取到constructor 属性时,会从 person 的原型也就是 Person.prototype 中读取,正好原型中有该属性

console.log(person.constructor === Person); // true

  扩展,万一原型没找到,那么原型的原型又是什么呢?其中Object.prototype.__proto__ 的值为 null 跟也就表示Object.prototype 没有原型,而图中红色的这条线就是原型链 

 

  看到这里,我们大致对__proto__和prototype也有了一定的模糊概念,那么他们又有什么用呢?

  实例对象的__proto__指向构造函数的prototype,从而实现了继承,prototype对象相当于所有实例化对象都可以访问的公共容器,接下来我们来看一段代码从而更好的理解“公共容器”

function Person(name,age) {
        this.name = name
        this.age = age
    }
    Person.prototype.sayName = function (){
        console.log(this.name);
    }

    var person1 = new Person('Andy',13);
    var person2 = new Person('Mary',18);

    person1.sayName();//Andy
    person2.sayName();//Mary

 

三、实例理解原型链 

  1、原型链属性查找

    首先我们来看一段代码:

      function Fun() {
            this.add = function (x, y) {
                return x + y;
            }
        }

        Fun.prototype.add = function (x, y) {
            return x + y + 10;
        }

        Object.prototype.subtract = function (x, y) {
            return x - y;
        }

        var fun = new Fun();
        console.log(fun.add(1, 2)); //结果是3,而不是13
        console.log(fun.subtract(1, 2)); //结果是-1    

  可以看出当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止,如果查找到达原型链的顶部 ,也就是 Object.prototype ,但是仍然没有找到指定的属性,就会返回 undefined

 

  2、this指向问题,

    sayName这个方法内部使用了this.name,那么这个this的指向是什么么?我们可以看到是person调用的sayName,隐式调用,this就指向person,而person的name就是Andy

   function Person(name) {
        this.name = name
    }
    Person.prototype.sayName = function (welcome){
        console.log(welcome,this.name);
    }
var person = new Person('Andy'); person.sayName('hello');//hello Andy

 

注:原型和原型链的具体应用可以看https://www.cnblogs.com/WuAnqi/p/15405247.html

posted @ 2021-10-13 21:23  打遍天下吴敌手  阅读(2258)  评论(0编辑  收藏  举报