在"Javascript學習手冊"中,P.127,有個範例不大懂怎麼運作的,程式如下:
const f = (function(){
let count = 0;
return function(){
return `I have been called ${++count} time(s).`;
}
})();
f(); //I have been called 1 time(s).
f(); //I have been called 2 time(s).
想問的是:
Q.為什麼第二次呼叫時.會得到結果"I have been called 2 time(s)."
而不是"I have been called 1 time(s)."
我的理解是,第二次呼叫後,在let count = 0,不是就重0開始了嗎?怎麼會跳過這行呢?
因為小弟剛學習JavaScript,請各路好手多多見諒...
因為閉包……
實際上你第一個f();
跑完之後,這個f
就已經是一個物件,內容是
function(){
return `I have been called ${++count} time(s).`;
}
往後的程式中,count會變成只有f這個物件能存取的私有變數,因為已經建立,所以並不會再被建立一次。
比較一下
const f = (function(){
let count = 0;
return function(){
return `I have been called ${++count} time(s).`;
}
})();
function g ()
{
let count = 0;
return `I have been called ${++count} time(s).`;
}
console.log(f());
console.log(f());
console.log(g());
console.log(g());
(function () { ... })(); 是一個[自調用函數],是會即時執行的。
[自調用函數]做了2個動作:-
const f = (function () { ... })(); 就是把[自調用函數]的[返回值],給予常數f。效果相等於 const f = function() { return 'I have been called ${++count} time(s).'; };
因此,這個範例的效果,就相等於
let count = 0;
const f = function() { return `I have been called ${++count} time(s).`; };
f(); //I have been called 1 time(s).
f(); //I have been called 2 time(s).
這一篇解釋的不錯,我節錄一小段。
for (var i = 1; i <= 5; i++) {
(function(j) {
setTimeout(function timer() {
console.log(j);
}, j * 1000);
})(i);
}
for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
@marlin12 已經是正解了。
剛好有人有點誤會變數的宣告意義。我就再說明一下。
認真來說。變數宣告中常用的就是 var 這個。其實還有另外let、const很少人會用到。
var的變數宣告會比較自由性。一般我會將其視為廣域性宣告。
javascript有個特性。其實無論是if、for等有應用到{}的。都可以將其視為一個區域。
var的特性可以各自在各自的區域宣告其對應的延伸區城
let的特性其實就像是一個私域性宣告的特性。它擁有保留私域變數及單獨使用的特性。
const則是常數宣告的意思。相信有在使用後端語言的人對於常數並不陌生才對。
也就是一但第一次宣告後。同時擁有全域性及不可變動的特性存在。
以下幾個例子說明。
// 宣告變數 a
var a = 10;
if(true){
// 在if(block scope)中宣告變數 b
var b = 20;
}
console.log(a) // 輸出:10
console.log(b);// 輸出:20
以下是let的特性
// 宣告變數 a
var a = 10;
if(true){
// 在if(block scope)中宣告變數 b
let b = 20;
console.log(b);// 輸出:20
}
console.log(a) // 輸出:10
console.log(b);// 無值,且會得到一個 is not defined 的錯誤
以下為 const
const PI = 3.1415926;
$(".diameter").keyup(function(){
console.log(PI) // 輸出:3.1415926
});
PI = 123456; //會直接報錯
console.log(PI) // 輸出:3.1415926
其實如果有再用 eslint 之類的 linter 的話
如果用 var
很多都會建議你改用 let 或 const
google曾經推一個 js 的 strong mode
直接把 var Deprecated
如果在這 mode 底下使用 var
會直接 throw error
因為大部分情況來說
var 所能做的
let/const 也能做
甚至會比var做得更好
也不會有一些使用 var 可能會有的問題
這篇也把一些問題點出
let/const 應該只會越來越常見
var的使用則會越來越少
沒ie的話,我應該早就把var廢掉了。
ie 11 以下的瀏覽器應該越來越難用了XD
我完全無視ie了。
目前如果有客戶要求ie也要能用的話。我直接將開發價格提高至少2倍以上。
再問客戶要不要。
我也直接跟客戶說,要ie能用,我就得花2倍以上的時間。拿2倍以上的開發金是很正常的事。ie就是這樣機車麻煩。
不是不做,只是更麻煩開發。所以費用不同。
let跟const都是block scope,只是const是宣告常數,let宣告變數,作用範圍都是在block(大括號)之內。當然,如果是在global scope宣告,作用就是在global scope。
{const a = 'test'}
console.log(a);
這樣會拋出例外(ReferenceError: a is not defined)。
喔!!原來const還是拖離不了js的block特性啊。
看樣子我又誤解了。
可能我都是當全域宣告。都是直接在最外層宣告。沒去注意這件事。
這下又導正我一個觀念了。