徹底理解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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM