一段用於增強顯示的程式碼如下:
for(var i=0;i<aLi.length;i++){
var oldColor=null;
aLi[i].onmouseover=function(){
oldColor=this.style.backgroundColor;
this.style.backgroundColor="#ccc";
}
aLi[i].onmouseout=function(){
this.style.backgroundColor=oldColor;
}
}
在這裡this.style是不能用aLi[i].style代替的,因為i早已循環完畢;
但如果i的值用let聲明,就完全不一樣,事件函數內也能準確調用i的值:
for(let i=0;i<aLi.length;i++){
var oldColor=null;
aLi[i].onmouseover=function(){
oldColor=this.style.backgroundColor;
consol.log(i);
aLi[i].style.backgroundColor="#ccc";
}
aLi[i].onmouseout=function(){
this.style.backgroundColor=oldColor;
}
}
事件函數觸發時,不應該是報錯找不到i麼?為什麼能成功運行
世界只因有你2017-06-12 09:30:06
ES6 新增了let指令,用來宣告變數。它的用法類似var,但是所宣告的變量,只在let指令所在的程式碼區塊內有效。
{
let a = 10;
var b = 1;
}
a // ReferenceError: a is not defined.
b // 1
上面程式碼在程式碼區塊之中,分別用let和var宣告了兩個變數。然後在程式碼區塊之外呼叫這兩個變量,結果let宣告的變數報錯,var宣告的變數回傳了正確的值。這表明,let聲明的變數只在它所在的程式碼區塊有效。
for迴圈的計數器,就很適合使用let指令。
for (let i = 0; i < 10; i++) {
// ...
}
console.log(i);
// ReferenceError: i is not defined
上面程式碼中,計數器i只在for迴圈體內有效,在循環體外引用就會報錯。
下面的程式碼如果使用var,最後輸出的是10。
var a = [];
for (var i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 10
上面程式碼中,變數i是var指令宣告的,在全域範圍內都有效,所以全域只有一個變數i。每一次循環,變數i的值都會改變,而循環內被賦給數組a的函數內部的console.log(i),裡面的i指向的就是全域的i。也就是說,所有陣列a的成員裡面的i,指向的都是同一個i,導致運行時輸出的是最後一輪的i的值,也就是10。
如果使用let,宣告的變數只在區塊級作用域內有效,最後輸出的是6。
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6
上面程式碼中,變數i是let宣告的,目前的i只在本輪循環有效,所以每一次迴圈的i其實都是一個新的變量,所以最後輸出的是6。你可能會問,如果每一輪循環的變數i都是重新聲明的,那它怎麼知道上一輪循環的值,從而計算出本輪循環的值?這是因為 JavaScript 引擎內部會記住上一輪循環的值,初始化本輪的變數i時,就在上一輪循環的基礎上進行計算。
另外,for迴圈還有一個特別之處,就是設定迴圈變數的部分就是一個父作用域,而迴圈體內部是一個單獨的子作用域。
for (let i = 0; i < 3; i++) {
let i = 'abc';
console.log(i);
}
// abc
// abc
// abc
上面程式碼正確運行,輸出了3次abc。這表示函數內部的變數i與迴圈變數i不在同一個作用域,有各自單獨的作用域。