Javascript入门1.0

Author Avatar
Aryb1n 5月 23, 2017

首先

是一个熟悉的段子

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html; charset=utf-8">
        <title>some test</title>
    </head>
    <body>
        <div>
            <a href=javascript:;>11</a>
        </div>
        <div>
            <a href=#>22</a>
        </div>
        <div>
            <a href=javascript:void(0);>33</a>
        </div>
        <script>
            var a_list = document.getElementsByTagName('a');
            for(var i = 0; i < 3; i++) {
                a_list[i].innerHTML = i;
            }
        </script>
    </body>
</html>

自豪的写了三种不同的不跳转的a,其实大概就是花式false

然后感觉..诶?我点让他点击弹出来点什么东西来,于是

var a_list = document.getElementsByTagName('a');
for(var i = 0; i < 3; i++) {
    a_list[i].onclick = function() {
        alert(i);
    };
}

结果悲剧了,为什么都弹出3啊(哇,假装好奇的样子)

开始回忆

这个问题的话,没有记错的话,是因为这里的i是一个全局变量,ES5没有块作用域,不过有个函数作用域
所以当每个人被点的时候,onclick被调用的时候,i=3, 所以都会alert(3);
开始好像有过疑问,为什么不是a_list[0]绑定onclick的时候就变成了

function() {
    alert(0);
}

这样子的呢,hhhhhh~我也不知道

找到解决办法

以前用过的

  1. 使用ES6
    这个办法我知道使用let

  2. 使用一个闭包
    一直以来我就是用的这个

    var a_list = document.getElementsByTagName('a');
    for(var i = 0; i < 3; i++) {
     a_list[i].onclick = (function(arg_i) {
         return function() {
             alert(arg_i);
         }
     })(i);
    }
    

    当时感觉这种写法特别帅

    别写错了.要return一个function的,别把alert写在立即执行的匿名函数里

剩下几种就是今天学到的了

  1. 把i存到每个对象里

    var a_list = document.getElementsByTagName('a');
    for(var i = 0; i < 3; i++) {
     a_list[i].arg = i;
     a_list[i].onclick = function() {
         alert(this.i);
     };
    }
    

    不够帅气,但很简单直观

  2. 匿名函数往外写了一层?

    var a_list = document.getElementsByTagName('a');
    for(var i = 0; i < 3; i++) {
     (function(arg) {
         a_list[i].onclick = function() {
             alert(arg);
         };
     })(i);
    }
    

    其实相当于把i变量绑定到匿名函数里作为一个局部变量(其实个人感觉传进来的参数和局部变量在很多地方都是相似的)了,相当于是利用了传说中的函数作用域

  3. 这次是真的用了一个局部变量

    var a_list = document.getElementsByTagName('a');
    for(var i = 0; i < 3; i++) {
     (function() {
         var arg = i; //这个arg虽然用了var但不是全局变量
         a_list[i].onclick = function() {
             alert(arg);
         };
     })();
    }
    

好了皆大欢喜
另外,看到一句话

绝大多数的同步的地方改成异步都都可以用上述方法,只要将需要异步的部分(通常是从某一行开始到函数末尾)包含在闭包中,就可以进行异步处理了