[快速入门前端 55] JavaScript:Global Scope 全域和 Local Scope 区域

Scope 作用域

Scope 是指在 JavaScript 程式中,一个变数可用 (或有效) 的範围,而在这个有效範围之外,变数是无法被使用的。举个常见的例子,我们在 Function 中定义的变数,无法在函式外取得,这也是为什么我们需要使用 return 回传的方式将计算出来的结果返回到函式呼叫处的原因。
在 JavaScript 中,Scope 主要又分为两大类 - Global Scope (全域) 及 Local Scope (区域)。

Global Scope 全域

在 Global Scope (全域) 中「宣告」的变数,也就是指在 JavaScript 档案最外层 (所有 Function 和区块之外) 被宣告的变数,被称为全域变数 (Global Variables)。全域变数可以从网页的任何地方,包括每个 Function、区块中进行赋值、取值等操作。

如下範例,程式最外层中分别有两种方法定义的全域变数 ab,不管在单纯的 if 区块function 函式 内都可以取得该变数。

let a = 1;var b = 2;if (true) {    console.log(a); // 1    console.log(b); // 2}function add() {    console.log(a); // 1    console.log(b); // 2};add(); // 呼叫 add()

Local Scope 区域

Local Scope (区域) 则和全域变数相反,是指在 Fucntion 函式Block 区块 内所宣告的变数,这类变数无法在宣告区域之外使用,所以被称为区域变数。
而区域变数又因最早的 var 及后来在 ES6 新增的 let 两种宣告方式有效範围的差别分为 Function Scope 函式作用域Block Scope 区块作用域

Function Scope 函式作用域

函式作用域是指在在函式中宣告的变数只能在函式区块内作用,是基于 var 以函式作为区块分隔的特性而来。也就是说在使用 var 时,所有不在 Function 内宣告的变数都是全域的。
有点複杂http://img2.58codes.com/2024/emoticon02.gif,以下用几个範例来说明:

var 是以 Function Scope 作为变数的有效範围,在函式内宣告的变数只能在函式内作用
function add() {    var x = 2;    console.log(x); // 2};add();console.log(x); // 报错,无法取得 x
所有在函式外(包括 if 区块内)宣告的变数对 var 来说都是全域的
var a = 1;if (true) { // if 不是 function    var b = 2; // 对 var 来说 b 也是全域变数,在任何地方都能使用}console.log(a); // 1console.log(b); // 2
判断是区域或全域变数的基準是变数「宣告」的位置,而非首次赋值的位置
var a; // 在最外层宣告function add () {    a = 2 // 在函式中赋值}add();console.log(a); // 2
只要没有在 Function 内进行宣告的都是全域变数 (包含没有宣告直接在函式内使用的变数)
// a 未宣告function add() {    a = 3; // 只在 function 中赋值,没有进行宣告,不算区域变数    // 未宣告直接使用,不符合规範但 var 不会报错};add();

Block Scope 区块作用域

Block Scope 区块 出现是基于 ES6 中新宣告方式 let 之作用域与 var 不同而来的概念,使用 let 宣告时,在区块 ({})中宣告的变数只会在 {} 中有效,也就是说若在 if{} 条件区块内使用 let 声明变数,则该变数为区域变数。

只要有被 {} 包裹,不管是条件区块或任何区块,let 宣告的变数都是区域变数
if (true) {    let a;}console.log(a); // not defined// 单纯用区块符号包裹也是区域变数{    let b;}console.log(b); // not defined

全域区域变数名称相同

当全域变数和区域名称相同时,例如已有一全域变数 a 后又在函式内宣告区域变数 a,我们要怎么知道现在在操作哪个变数呢?
答案是「找最近的」!
让我们先来看看 var 的情境:

在全域作用域宣告变数时,无论在哪都可以操作变数
var x = 1; // 全域console.log(x); // 1function add() {    console.log(x); // 1};add();console.log(x); // 1
有一全域变数 x 又在函式内宣告一次 x,则会将两个 x 视为不同的变数,找离自己最近的 (Function 内归 Function 内,全域归全域)
var x = 1; // 全域console.log(x);function add() {    var x = 5; // Function 内宣告同名变数,是区域变数    console.log(x); // 5    x = 10; // 会找最近的,所以在 Function 内操作的都是区域变数    console.log(x); // 10};add();console.log(x); // 1 区域变数不影响全域变数
函式内先使用变数再进行宣告,宣告前值为 undefined,不会拿全域变数的值
var x = 1; // 全域console.log(x);function add() {    console.log(x); // undefined    var x = 5;    console.log(x); // 5};add();console.log(x);

接着来看看 let

基本上 let 的规则与 var 大致相同,若在全域和区域有相同名称的变数时,会找最近的
let x = 1; // 全域console.log(x); // 1function add() {    let x = 5;    console.log(x); // 5};add();console.log(x); // 1
不同的是 let 无法先使用再宣告,所以下範例会报错
let x = 1; // 全域console.log(x); // 1function add() {    console.log(x); // 报错,区域内宣告同名变数,所以与全域的 x 为不同变数    let x = 5;    console.log(x);};add();console.log(x);

结论

对于 letvar 这两种宣告方式,其实在全域和区域的概念大致相同,差别在于两者的「作用域」分别是 区块函式,只要分清楚两种方法的差异就可以很容易弄懂其中的逻辑啦!


上一篇:[快速入门前端 54] JavaScript:Function 函式 (2) 参数和回传
下一篇:[快速入门前端 56] JavaScript:Array 阵列 (3) 常见阵列操作方法
系列文章列表:[快速入门前端] 系列文章索引列表


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章