zoukankan      html  css  js  c++  java
  • 立即执行函数

    原文:http://web.jobbole.com/82520/

    "立即执行函数"其实就是"立即执行函数表达式",这句话很重要,下面的文字就是描述为什么这么说。

    函数表达式
    
    var fn = funtion(){
        /* code */
    }
    
    函数声明
    
    function fn(){
      /* code */  
    }

    函数声明必须是一个单独的JavaScript语句。

    1.介绍函数(函数声明,函数表达式)

    在JavaScript中,每一个函数在被调用的时候都会创建一个执行上下文,在该函数内部定义的变量和函数只能在该函数内部使用,而正是因为这个上下文,让我们在调用函数的时候能创建一些私有变量。

    (图1)

    为什么函数one可以访问外部的i的值,可以参考:原文https://github.com/creeperyang/blog/issues/16

    简单描述一下,函数上下文:每调用一次产生一个上下文,调用完毕后销毁。

     

    在该上下文中,有个规律,里面的函数可以访问外部的函数的属性,而外部却不能访问函数的内部属性。在es6中就有块的概念了。

    为啥有这个规律?

    最小访问原则:

    不允许你代码中所有的东西在任意地方都可用的好处是什么?其中一个优势,是作用域为你的代码提供了一个安全层级。计算机安全中,有个常规的原则是:用户只能访问他们当前需要的东西。

    想想计算机管理员吧。他们在公司各个系统上拥有很多控制权,看起来甚至可以给予他们拥有全部权限的账号。假设你有一家公司,拥有三个管理员,他们都有系统的全部访问权限,并且一切运转正常。但是突然发生了一点意外,你的一个系统遭到恶意病毒攻击。现在你不知道这谁出的问题了吧?你这才意识到你应该只给他们基本用户的账号,并且只在需要时赋予他们完全的访问权。这能帮助你跟踪变化并记录每个人的操作。这叫做最小访问原则。眼熟吗?这个原则也应用于编程语言设计,在大多数编程语言(包括 JavaScript)中称为作用域。(引用http://web.jobbole.com/91134/)

    回到问题的核心。

    修改图(1)的代码.

    // makeCounter函数返回的是一个新的函数,该函数对makeCounter里的局部变量i享有使用权
    function makeCounter() {
      // i只是makeCounter函数内的局部变量
      var i = 0;
     
      return function() {
        console.log( ++i );
      };
    }
     
    // 注意counter和counter2是不同的实例,它们分别拥有自己范围里的i变量
     
    var counter = makeCounter();
    counter(); // 1
    counter(); // 2
     
    var counter2 = makeCounter();
    counter2(); // 1
    counter2(); // 2
     
    i; // 报错,i没有定义,它只是makeCounter内部的局部变量

    那么,立即执行函数其实就是加一个小括号,那么

    //列子1
    
    function (){
     /*code*/        
    }()
    
    //报错SyntaxError: Unexpected token (

    在JavaScript代码解释时,当遇到function关键词时,会默认把他当成一个函数声明,而不是函数表达式,如果没有把它显视地表达成函数表达式,就报错了,因为函数声明需要一个函数名,而上面的代码中函数没有函数名。(以上代码,也正是在执行到第一个左括号(时报错,因为(前理论上是应该有个函数名的。)

    加个函数名

    //列子2
    
    function foo(){
    /*code*/
    }()
    
    //依旧报错 SyntaxError: Unexpected token )

    为什么会这样?在一个表达式后面加上括号,表示该表达式立即执行;而如果是在一个语句后面加上括号,该括号完全和之前的语句不搭嘎,而只是一个分组操作符,用来控制运算中的优先级(小括号里的先运算)。

    如果没有优先级的话,这句话是对的,但是小括号的优先级比function的高,所以就会报错

    //修改之后的代码
    
    (function foo(){
     /*code*/
    }())

    为什么这样就能立即执行并且不报错呢?因为在javascript里,括号内部不能包含语句,当解析器对代码进行解释的时候,先碰到了(),然后碰到function关键字就会自动将()里面的代码识别为函数表达式而不是函数声明

    还有一些其他的骚操作:

    // 这是一个自执行函数,函数内部执行的是自己,递归调用
    function foo() { foo(); }
     
    // 这是一个自执行匿名函数,因为它没有函数名
    // 所以如果要递归调用自己的话必须用arguments.callee
    var foo = function() { arguments.callee(); };
     
    // 这可能也算是个自执行匿名函数,但仅仅是foo标志引用它自身
    // 如果你将foo改变成其它的,你将得到一个used-to-self-execute匿名函数
    var foo = function() { foo(); };
     
    // 有些人叫它自执行匿名函数,尽管它没有执行自己,只是立即执行而已
    (function(){ /* code */ }());
     
    // 给函数表达式添加了标志名称,可以方便debug
    // 但是一旦添加了标志名称,这个函数就不再是匿名的了
    (function foo(){ /* code */ }());
     
    // 立即执行函数也可以自执行,不过不常用罢了
    (function(){ arguments.callee(); }());
    (function foo(){ foo(); }());
  • 相关阅读:
    C#listbox使用方法
    poj 3894 System Engineer (二分图最大匹配--匈牙利算法)
    Java实现 蓝桥杯VIP 算法训练 连接字符串
    Java实现 蓝桥杯VIP 算法训练 连接字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 比较字符串
    Java实现 蓝桥杯VIP 算法训练 黑白无常
  • 原文地址:https://www.cnblogs.com/damai/p/9008655.html
Copyright © 2011-2022 走看看