面试中常考的题,把想到的方法都整理一下,代码如下:

1
2
<ul id="list">
</ul>
1
2
3
4
5
6
7
8
9
10
var list = document.getElementById("list");
for (var i = 1; i <= 5; i++) {
var item = document.createElement("li");
item.appendChild(document.createTextNode("列表 " + i));

item.onclick = function (e) {
console.log("列表 " + i + " 被点击.");
};
list.appendChild(item);
}

上面这段代码的意图是创建5个li,点击不同的li能够打印出当前li的序号。但是点击任何li打印出来的都是“列表 6 被点击“,因为i是函数级变量,5个内部函数都指向了同一个i ,而i最后一次赋值是5,当点击时i已经是6了。

第一种

在函数定义里的变量,是会变的。要想让他变成某个具体的数,就要在当他等于那个具体的值时立即执行它

1
2
3
4
5
6
7
8
9
10
11
var list = document.getElementById("list");
for (var i = 1; i <= 5; i++) {
var item = document.createElement("li");
item.appendChild(document.createTextNode("列表 " + i));
(function(j){
item.onclick = function (e) {
console.log("列表 " + j + " 被点击.");
};
})(i);
list.appendChild(item);
}

第二种

1
2
3
4
5
6
7
8
9
10
11
12
var list = document.getElementById("list");
for (var i = 1; i <= 5; i++) {
var item = document.createElement("li");
item.appendChild(document.createTextNode("列表 " + i));
var hadleClik = function(item, i) {
item.onclick = function(e) {
console.log("列表 " + i + " 被点击.");
};
}
hadleClik(item, i);
list.appendChild(item);
}

第三种

1
2
3
4
5
6
7
8
9
10
11
12
var list = document.getElementById("list");
for (var i = 1; i <= 5; i++) {
var item = document.createElement("li");
item.appendChild(document.createTextNode("列表 " + i));
var handleClik = function(item, i) {
item.onclick = function(e) {
console.log("列表 " + i + " 被点击.");
};
}
hadleClik(item, i);
list.appendChild(item);
}

第四种

1
2
3
4
5
6
7
8
9
10
11
12
13
var list = document.getElementById("list");
for (var i = 1; i <= 5; i++) {
var item = document.createElement("li");
item.appendChild(document.createTextNode("列表 " + i));

item.onclick = (function(i) {
return function() {
console.log("列表 " + i + " 被点击.");
}
})(i);

list.appendChild(item);
}

第五种

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var list = document.getElementById("list");
for (var i = 1; i <= 5; i++) {
var item = document.createElement("li");
item.appendChild(document.createTextNode("列表 " + i));
var handleClik = function(i){
return function(){
console.log("列表 " + i + " 被点击.");
}
}
item.onclick = handleClik(i);

list.appendChild(item);
}

第六种

用了let后,j 变成块级域(也就是花括号中的块,每进入一次花括号就生成了一个块级域),所以 5 个内部函数指向了不同的 j 。

1
2
3
4
5
6
7
8
9
10
var list = document.getElementById("list");
for (var i = 1; i <= 5; i++) {
var item = document.createElement("li");
item.appendChild(document.createTextNode("列表 " + i));
let j = i;
item.onclick = function (e) {
console.log("列表 " + j + " 被点击.");
};
list.appendChild(item);
}