xia的小窩

一起來coding和碼字吧

0%

js-範圍

範圍 vs 存在

如果變數不存在,它就不會在範圍內。

範圍指的是 : 目前在執行的程式段落可以看到與操作某個識別碼。另一方面,存在代表 有一個識別碼保存了某些已經分配 ( 保留 ) 給它的記憶體。

語彙與動態範圍

我們舉個例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function test1(){
console.log("f1")
}
function test2() {
console.log("f2")
}

test1();
test2();
test1();

// f1
// f2
// f1

這是一般的程式碼,可以一目瞭然,不過有些時候不一定能明確地看出範圍

1
2
3
4
5
6
7
const x = 10;
function test(){
console.log(x);
console.log(y);
}
const y = 2;
test();

當我們定義 test( ) 的時候,變數 x 是存在的,但 y 不存在,然後我們宣告了 y 並呼叫 test( ) ,你可以看到,當 test 被呼叫時, x 在 test 的本文範圍內,但 y 不在。

全域變數

其實全域變數沒有這麼不好,不好的是濫用全域變數的部分。

1
2
3
4
let a = 10;          // 全域
function test(){
console.log(`a : ${a}`);
}

這樣是沒有結果的,我們可以再把它放進物件裡

1
2
3
4
5
6
7
let test = {
nums : 14,
}
function f1(){
console.log(`nums : ${test.nums}`);
}
f1();

這邊要想一個問題….如果物件裡的鍵超過一定的數量時……

1
2
3
function f1(test){
console.log(`nums : ${test.nums}`);
}

區塊範圍

1
2
3
4
5
6
7
8
9
10
11
12
console.log("before")
{
let x = 10;
console.log(`inside and x = ${x}`)
}
console.log(`outside and x = ${x}`)

// before
// inside and x = 10
// console.log(`outside and x = ${x}`)
// ^
// ReferenceError: x is not defined

這邊可以看得出作用範圍了

變數遮蓋

1
2
3
4
5
6
7
8
{
const x = 'bread'
console.log(x);
}
console.log(typeof x);

// bread
// undefined

超出範圍會出現 undefined

在撰寫的時候也要考慮 嵌套 的問題

1
2
3
4
5
6
7
{
{
{
// ...
}
}
}

類似上面這種的要小心注意

函式、Closure( 閉包 )與語彙範圍

前面都在討論區域,一目瞭然的是在縮排後只需要看 { } 就可以知道它的範圍

但是在 modern JavaScript 裡,函式會根據它的需求而定義,他們被指派給變數或物件特性、加到陣列裡面、傳入傳出函式……

我們來看個 closure 的範例 ( closure 可以想成在函式周圍關閉範圍 )

1
2
3
4
5
6
7
8
9
10
let test; 
{
let f1 = 'a';
test = function () {
console.log(f1);
}
}
test();

// a

立即呼叫函式運算式

我們先來看看這個東西長怎樣

1
2
3
(function(){
// 隨意
})();

這個東西就是 IIFE ( 立即呼叫函式運算式 )

我們直接來看個例子

1
2
3
4
5
6
7
8
const msg = (function(){
const test = 'Mytest';
return `${test.length}`
})();
// () -> function()
console.log(msg);

// 6

很明顯的,這個變數 test 在 IIFE 的範圍內是很安全的,我們可以從裡面傳出任何想要的東西。

雖然 ES6 的區塊範圍變數在某種程度上可以減少對 IIFE 的依賴,但 IIFE 仍然很常見,而且當你想要建立一個 closure 時,並將某個東西傳出去還是很實用的。