JS中的「水花兄弟」--做用域鏈和原型鏈

做用域鏈

什麼是做用域?

  首先咱們要知道在ES6以前JS是沒有塊級做用域的。那時只能經過函數來建立局部做用域,那麼做用域究竟是什麼呢?首先咱們須要瞭解的是做用域作什麼的?當JavaScript引擎在某一做用域中碰見變量和函數的時候,須要可以明確變量和函數所對應的值是什麼,因此就須要做用域來對變量和函數進行查找,而且還須要肯定當前代碼是否對該變量具備訪問權限。說白了所謂做用域,就是變量或者是函數能做用的範圍。bash

那麼JavaScript中有哪些做用域呢?函數

  • 全局做用域和局部做用域

咱們所定義的除了函數裏的變量之外的全部變量都在全局做用域內。this

var str ="hello world"
    var arr =[1,2,3]
    var obj ={name:"cxk"}
    var a=1;
    function f(){
        var b=2;
    }
複製代碼

上面定義的全部變量只有b不在全局做用域裏,由於b被定義在f函數內,與此同時b所在的做用域就叫作局部做用域。spa

  • 塊級做用域

ES6以後出現了let和const能夠定義變量,而它們所定義的變量就存在着塊級做用域。prototype

let a=1;
}
consloe.log(a)
複製代碼

運行代碼會報錯:a is not defined 代碼中的{}就是一個因爲let定義變量而造成的塊級做用域,a這個變量只有在{}中才能訪問。3d

什麼是做用域鏈?

  變量隨着做用長輩函數一級一級往上搜索,直到找到爲止,找不到就報錯,這個過程就是做用域鏈起的做用。咱們也能夠從執行上下文這個角度來理解做用域鏈這個概念。code

  • 全局執行上下文:當咱們開始運行代碼後,就會造成一個全局執行上下文,這裏麪包括了全局變量以及沒有在任何函數內部的全局函數。全局執行上下文只會在代碼運行時建立一次。
  • 函數執行上下文:當咱們的代碼運行到函數時就會產生一個函數執行上下文,這裏麪包括了本身函數內部定義的局部變量以及父函數的執行上下文。每調用一次函數就會造成一個函數執行上下文,因此函數執行上下文能夠有不少個。
function Outer(){
    var outer = 'outer';
    Inner();
    function Inner(){
        var inner = 'inner';
        console.log(outer,inner) // outer inner
    }
}
複製代碼

當咱們調用Inner函數時它會在本身的函數執行上下文找outer和inner變量,結果只找到了inner。那麼這時它就去本身的父函數Outer中找outer變量,找到了就返回給Inner函數。因此這種逐級去本身的父函數的執行上下文中搜索變量的方式就是做用域鏈。orm

圖解:

那麼到此做用域和做用域鏈就介紹完畢了。

原型鏈

什麼是原型?

  在JavaScript中一切皆對象,那麼函數也是一個對象。因此這函數裏也有不少屬性,這其中必然有一個prototype屬性 cdn

這裏的prototype指向的是一個對象(原型對象),原型對象中的方法和屬性均可以被函數的實例所共享。所謂的函數實例是指以函數做爲構造函數建立的對象,這些對象實例均可以共享構造函數的原型的方法。

什麼是原型鏈?

var Person = function(name){
    this.name = name;
}
Person.prototype.say = function(){
    console.log( this.name)
};

var person = new Person('cxk');
person.say();//cxk

複製代碼

上面的例子中,對象person是new Person建立的實例,在使用new操做符調用函數時主要執行如下幾個步驟:對象

1,建立新的對象,並將函數的this指向新建立的對象

2,執行函數

3,返回新建立的對象

4,將本身的__proto__(隱式原型對象)指向構造函數的原型對象

與此同時原型對象中的constructor也指向了構造器

因爲原型對象也是一個對象,因此它也有一個__proto__指向它的構造器Object,一樣的Object也有一個__proto__指向Null。

因此當咱們想使用對象的某些方法時例如obj.a()會先到本身的__proto__對象中找,若是沒有就會去它的原型對象的原型對象中找,也就是__proto__.proto 。以此類推...

這種搜索的軌跡,形似一條長鏈,又因prototype在這個遊戲規則中充當連接的做用,因而咱們把這種實例與原型的鏈條稱做 原型鏈 。

至此做用域鏈和原型鏈介紹完了,若有錯誤還望指正,謝謝。

相關文章
相關標籤/搜索