亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

全部開發者教程

JavaScript 入門教程

作用域

作用域即代碼片段的有效范圍,這里的代碼片段可以是一個函數、一個變量等。

在 JavaScript 中,通常被拿來討論的是 全局作用域函數作用域

1. 全局作用域

在全局環境下定義的變量、函數,都屬于全局作用域的范圍,也就是這些變量、函數在任何地方都能被訪問。

var number = 1;

var fn = function() {
  console.log('我是一個全局下的函數');
  console.log('訪問全局下的 number: ', number);
};

fn();

圖片描述

全局的作用域很好理解,即全局下的變量、函數在任何地方都能被訪問到。

在 ES6 的模塊化規范中,一個模塊就是一個 js 文件,所以如果在 ES6 的模塊的最頂層聲明變量和函數,是不屬于全局的。

2. 函數作用域

函數擁有自己的作用域,也就是說函數內聲明的變量和函數,只在函數內有效。

var fn = function() {
  var innerFn = function() {
    console.log('我是函數內的函數');
  };

  var str = '我是函數內的變量';

  innerFn();
  console.log(str);
};

fn();

console.log(str); // 輸出:ReferenceError: str is not defined

圖片描述

函數內的變量 str 在函數外部無法訪問到,因為其所在的作用域是函數 fn 的作用域,所以只在 fn 函數內能被訪問。

3. eval 的作用域

eval 根據調用的方式,其作用域也會發生變化。

如果直接調用 eval 則其作用域就是當前上下文中的作用域。如果間接性質的調用,比如通過一個 eval 的引用來調用,那作用域就是全局的。

var storeEval = eval;

(function() {
  storeEval('var number1 = 1;');
  eval('var number2 = 2');

  console.log('自執行匿名函數內輸出:', number2);
})();

console.log(number1); // 輸出:1
console.log(number2); // 輸出:ReferenceError: number2 is not defined

圖片描述

本身 eval 用到的情況就少,所以這種情況下做個了解即可。

4. 作用域鏈

理解了作用域,作用域鏈就很好理解了。

通常情況下,內層作用域擁有訪問上層作用域的能力,而外層無法訪問到內層的作用域。

var number = 1;

var fn = function() {
  console.log(number);

  var str = '字符串';
};

fn();

console.log(str); // 輸出:ReferenceError: str is not defined

由此可見作用域從內往外的。

var number1 = 1;
var fn1 = function() {
  var number2 = 2;

  var fn2 = function() {
    var number3 = 3;

    var fn3 = function() {
      console.log('fn3 內的輸出:');
      console.log(number1);
      console.log(number2);
      console.log(number3);
    }

    fn3();
  };

  fn2();
}

fn1();

圖片描述

例子中的 fn3 就具有訪問 fn2作用域、fn1作用域、全局作用域的能力。

圖片描述

這樣從內往外就形成了一條作用域鏈。

5. 利用函數作用域進行封裝

函數作用域最常用的場景之一就是隔離作用域。

因為函數有自己的作用域,所以很多庫、框架在實現的時候都會把內容寫在一個函數中。

(function() {
  var config = {};

  var fn = function() {
    // ...
  };

  window.$ = fn;
  window.jQuery = fn;
})();

這樣就不會污染到全局,只對外暴露想要暴露的部分。

6. 小結

有關作用域有更深入的內容,本篇探討的是最容易理解的部分。

理解作用域可以更好的組織代碼結構,減少各個上下文的污染。

在 ES6 中引入了塊及作用域的概念,這是在之前都沒有的,可以查閱 ES6 中對應的內容進行了解。