前端技巧知识(二)
(1)在JavaScript的非严格模式下,函数的实参集合与形参变量存在”映射“关系: 不管其中谁改变了,另外一个都会跟着改变
function fn(a) {
// => a = 10
arguments[0] = 1231
// => a = 1231
a = 123
// => arguments[0] = 123
}
fu(10)
//没有返回值 则为 undefined
在JS严格模式下 arguments和形参变量的映射关系被切断了,相互之间没有影响
"use strict"
// 使用严格模式
(2)示例问题
问题描述
以下代码的功能是要实现5个input按钮循环绑定click点击事件,绑定完成后点击1、2、3、4、5五个按钮分别会alert输出0、1、2、3、4五个字符。
问:
- 如下代码是否能实现?
- 如果不能实现那么现在的效果是什么样的?
- 应该怎么修改才能达到我们想要的效果,并说明原理?
<div id="btnBox">
<input type="button" value="button_1">
<input type="button" value="button_2">
<input type="button" value="button_3">
<input type="button" value="button_4">
<input type="button" value="button_5">
</div>
<script type="text/javascript">
var btnBox = document.getElementById('btnBox')
var inputs = btnBox.getElementsByTagName('input')
var len = inputs.length
for (var i = 0; i < len; i++) {
// => 循环结束 i = 5
inputs[i].onclick = function () {
alert(i)
}
}
</script>
上面的代码为什么不行?
所有的事件绑定都是异步编程(绑定的时候方法并没有执行,当触发点击事件,执行方法的时候,循环早就已经结束)
- 同步:JS中当前这个任务没有完成,下面的任务都不会执行,只有等当前的任务彻底完成,才会执行下面的任务;
- 异步:JS中当前这个任务没有完成,需要等一会才能完成,此时可以继续执行下面的任务。
解决办法
法一:自定义属性
for (var i = 0; i < len; i++) {
inputs[i].myIndex = i
inputs[i].onclick = function () {
alert(this.myIndex)
}
}
法二:闭包
for (var i = 0; i < len; i++) {
~function (i) {
inputs[i].onclick = function () {
alert(i)
}
}(i)
}
或
for (var i = 0; i < len; i++) {
inputs[i].onclick = (function (i) {
return function () {
alert(i)
}
}) (i)
}
// 这种方法性能并不是很好
法三: ES6(块级作用域)(let var const 知识)
for (let i = 0; i < len; i++) {
inputs[i].onclick = function () {
alert(i)
}
}