做用域與做用域鏈

什麼是做用域函數

就是一塊"地盤", 一個代碼段所在的區域,它是靜態的(相對於上下文對象), 在編寫代碼時就肯定了測試

做用域分類:全局做用域, 函數做用域, 沒有塊做用域(ES6有了)this

做用域的做用是隔離變量,不一樣做用域下同名變量不會有衝突spa

var a = 10,
  b = 20
function fn(x) {
  var a = 100,
    c = 300;
  console.log('fn()', a, b, c, x) // fn() 100 20 300 10
  function bar(x) {
    var a = 1000,
      d = 400
    console.log('bar()', a, b, c, d, x)
  }

  bar(100) // bar() 1000 20 300 400 100
  bar(200) // bar() 1000 20 300 400 200
}
fn(10)

 

 

 

做用域與執行上下文code

全局做用域以外,每一個函數都會建立本身的做用域,做用域在函數定義時就已經肯定了。而不是在函數調用時對象

全局執行上下文環境是在全局做用域肯定以後, js代碼立刻執行以前建立blog

函數執行上下文環境是在調用函數時, 函數體代碼執行以前建立作用域

做用域是靜態的, 只要函數定義好了就一直存在, 且不會再變化;上下文環境是動態的, 調用函數時建立, 函數調用結束時上下文環境就會被釋放io

聯繫:上下文環境(對象)是從屬於所在的做用域:全局上下文環境==>全局做用域,函數上下文環境==>對應的函數使用域console

var a = 10,
  b = 20
function fn(x) {
  var a = 100,
    c = 300;
  console.log('fn()', a, b, c, x)
  function bar(x) {
    var a = 1000,
      d = 400
    console.log('bar()', a, b, c, d, x)
  }

  bar(100)
  bar(200)
}
fn(10)

 

 

 

做用域鏈

多個上下級關係的做用域造成的鏈, 它的方向是從下向上的(從內到外)

查找變量時就是沿着做用域鏈來查找的

查找一個變量的查找規則

在當前做用域下的執行上下文中查找對應的屬性, 若是有直接返回, 不然進入2

在上一級做用域的執行上下文中查找對應的屬性, 若是有直接返回, 不然進入3

再次執行2的相同操做, 直到全局做用域, 若是還找不到就拋出找不到的異常

var a = 2;
function fn1() {
  var b = 3;
  function fn2() {
    var c = 4;
    console.log(c); // 4
    console.log(b); // 3
    console.log(a); //2
    console.log(d); // 報錯:d is not defined
  }

  fn2();
}
fn1();

 

 

做用域測試題

var x = 10;
function fn() {
  console.log(x); // 10,由於fn的做用域再也不show方法裏,定義方法的時候做用域就肯定了
}
function show(f) {
  var x = 20;
  f();
}
show(fn);
var fn = function () {
  console.log(fn) // 輸入函數自己
}
fn()

var obj = {
  fn2: function () {
    console.log(obj.fn2) // 這樣纔是找obj對象下的fn2
    console.log(this.fn2) // 這樣纔是找obj對象下的fn2

    // 報錯:fn2 is not defined,先在這個方法裏面找fn2,若是沒有在外部做用域(window)找
    console.log(fn2)
  }
}
obj.fn2()
var fn = function () {
console.log(fn)
}
fn() // function定義,總共有兩個做用域:函數內部和全局上,函數內部沒有,找到全局有,因此打印出fn函數的定義

var obj = {
fn2: function () {
  console.log(fn2)
  // 想輸出fn2屬性的值
  // console.log(this.fn2) // obj.fn2也行, 但比較死
}
}
obj.fn2() //報錯,也是兩個做用域函數內部和全局的,函數內部沒有,全局也沒有因此fn2是沒有定義的,結果是報錯的
相關文章
相關標籤/搜索