zoukankan      html  css  js  c++  java
  • 复习JavaScript 5

    # 立即调用的函数表达式 复习
    
    ##函数的执行上下文##
    >在JavaScript里,任何function在执行的时候都会创建一个执行上下文,因为为function声明的变量和声明的function有可能只在该function内部。
    ```javascript
    // 由于该function里返回了另外一个function,其中这个function可以访问自由变量i
    // 所有说,这个内部的function实际上是有权限可以调用内部的对象。
    
    function makeCounter() {
        // 只能在makeCounter内部访问i
        var i = 0;
    
        return function () {
            console.log(++i);
        };
    }
    
    // 注意,counter和counter2是不同的实例,分别有自己范围内的i。
    
    var counter = makeCounter();
    counter(); // logs: 1
    counter(); // logs: 2
    
    var counter2 = makeCounter();
    counter2(); // logs: 1
    counter2(); // logs: 2
    
    alert(i); // 引用错误:i没有defind(因为i是存在于makeCounter内部)。
    ```
    ##自执行函数表达式##
    之前的提过函数表达式可以立即运行,类似下面:
    ```javascript
    // 下面2个括弧()都会立即执行
    
    (function () { /* code */ } ()); // 推荐使用这个
    (function () { /* code */ })(); // 但是这个也是可以用的
    
    // 由于括弧()和JS的&&,异或,逗号等操作符是在函数表达式和函数声明上消除歧义的
    // 所以一旦解析器知道其中一个已经是表达式了,其它的也都默认为表达式了
    // 不过,请注意下一章节的内容解释
    
    var i = function () { return 10; } ();
    true && function () { /* code */ } ();
    0, function () { /* code */ } ();
    
    // 如果你不在意返回值,或者不怕难以阅读
    // 你甚至可以在function前面加一元操作符号
    
    !function () { /* code */ } ();
    ~function () { /* code */ } ();
    -function () { /* code */ } ();
    +function () { /* code */ } ();
    
    // 还有一个情况,使用new关键字,也可以用,但我不确定它的效率
    // http://twitter.com/kuvos/status/18209252090847232
    
    new function () { /* code */ }
    new function () { /* code */ } () // 如果需要传递参数,只需要加上括弧()
    ```
    ##闭包的神奇##
    自执行的函数表达式当然也是函数,所以它理所应当可以传入参数。闭包的神奇就在于它可以有效地保存闭包内的状态。
    ```javascript
    // 这个代码是错误的,因为变量i从来就没背locked住
    // 相反,当循环执行以后,我们在点击的时候i才获得数值
    // 因为这个时候i操真正获得值
    // 所以说无论点击那个连接,最终显示的都是I am link #10(如果有10个a元素的话)
    
    var elems = document.getElementsByTagName('a');
    
    for (var i = 0; i < elems.length; i++) {
    
        elems[i].addEventListener('click', function (e) {
            e.preventDefault();
            alert('I am link #' + i);
        }, 'false');
    
    }
    
    // 这个是可以用的,因为他在自执行函数表达式闭包内部
    // i的值作为locked的索引存在,在循环执行结束以后,尽管最后i的值变成了a元素总数(例如10)
    // 但闭包内部的lockedInIndex值是没有改变,因为他已经执行完毕了
    // 所以当点击连接的时候,结果是正确的
    
    var elems = document.getElementsByTagName('a');
    
    for (var i = 0; i < elems.length; i++) {
    
        (function (lockedInIndex) {
    
            elems[i].addEventListener('click', function (e) {
                e.preventDefault();
                alert('I am link #' + lockedInIndex);
            }, 'false');
    
        })(i);
    
    }
    
    // 你也可以像下面这样应用,在处理函数那里使用自执行函数表达式
    // 而不是在addEventListener外部
    // 但是相对来说,上面的代码更具可读性
    
    var elems = document.getElementsByTagName('a');
    
    for (var i = 0; i < elems.length; i++) {
    
        elems[i].addEventListener('click', (function (lockedInIndex) {
            return function (e) {
                e.preventDefault();
                alert('I am link #' + lockedInIndex);
            };
        })(i), 'false');
    
    }
    ```
    ***
    感谢@汤姆大叔 的《深入理解JavaScript系列》指导我学习!
    
  • 相关阅读:
    未将对象引用设置到对象的实例--可能出现的问题总结
    Unity3d物体模型(实现旋转缩放平移自动旋转)
    Java实现斐波那契数列的多种方法
    Java实现斐波那契数列的多种方法
    Java实现斐波那契数列的多种方法
    Java实现斐波那契数列的多种方法
    Java实现斐波那契数列的多种方法
    Java中环境变量PATH与CLASSPATH的区别
    Java中环境变量PATH与CLASSPATH的区别
    Java中环境变量PATH与CLASSPATH的区别
  • 原文地址:https://www.cnblogs.com/ltchronus/p/3554850.html
Copyright © 2011-2022 走看看