本页使用了标题或全文手工转换

立即调用函数表达式

维基百科,自由的百科全书
跳到导航 跳到搜索

立即调用函数表达式(英文:immediately-invoked function expression,缩写:IIFE[1],是一种利用JavaScript函数生成新作用域的编程方法。

立即调用函数表达式可以令其函数中声明的变量绕过JavaScript的变量置顶声明规则,还可以避免新的变量被解释成全域变量或函数名占用全域变量名的情况。与此同时它能在禁止访问函数内声明变量的情况下允许外部对函数的调用。有时,这种编程方法也被叫做“自执行(匿名)函数”,但“立即调用函数表达式”是语义上最准确的术语。 [2][1][3][4]

用法[编辑]

立即调用函数表达式拥有数种不同的写法[5]。最常见的一种是将函数表达式字面量至于圆括号(分组运算符)之内,然后使用圆括号调用函数。[6][7]

(function() {
  // 这里的语句将获得新的作用域
})();

若要将作用域外变量传递进函数,则按下述方式书写:

(function(a, b) {
  // a == 'hello'
  // b == 'world'
})('hello', 'world');

开头的括号可能会因为解释器的分号自动插入特性造成一些问题。括号本用于明确字面量为表达式以与函数声明语句区分,但解释器可能将括号解释为对以上一行中结尾的变量名为名的函数的调用。在一些省略分号的程序中,可见将分号至于行首的做法。这样的分号被称为“防御性分号”[8][9],举例:

a = b + c
;(function() {  // 故意将分号放在这里
  // 代码
})();

如此书写,以防止语句被理解为对函数c的调用(c(...))。

例子[编辑]

理解立即调用函数表达式的关键在于认清JavaScript拥有函数作用域,但没有块作用域(ES6之前),且通过指针(而非复制)将变量传入一个函数闭包[10]

求值上下文(Evaluation context)[编辑]

缺少块作用域意味着一个在类似于for循环的块中声明的变量会被置顶到其所包含的函数中。如果一个内部函数依赖于一个外部变量,而该外部变量被外部函数更改,那么执行内函数就有些困难。举例,我们在声明函数之后,但在定义函数之前,改变一个变量的值。[11]

var v, getValue;
v = 1;
getValue = function() { return v; };
v = 2;
 
getValue(); // 2

当我们手动给v赋值时这结果似乎没什么问题。不过,如果getValue()是在一个循环中被定义的,那么就可能出现预想外的结果。

var v, getValue;
v = 1;
getValue = (function(x) {
  return function() { return x; };
})(v);
v = 2;

getValue(); // 1

此例中,function将 v 作为参数传入并立即调用,保护了内部函数的执行上下文。[12]

David Herman's Effective JavaScript contains an example illustrating the problems of evaluation context inside loops.[13] While Herman's example is deliberately convoluted it arises directly from the same lack of block scope.[14]

利用IIFE建立真正的私有函数和变量,并用闭包访问[编辑]

IIFEs are also useful for establishing private methods for accessible functions while still exposing some properties for later use.[15] The following example comes from Alman's post on IIFEs.[1]

var counter = (function(){
  var i = 0;

  return {
    get: function(){
      return i;
    },
    set: function( val ){
      i = val;
    },
    increment: function() {
      return ++i;
    }
  };
})();

// 'counter' is an object with properties, which in this case happen to be
// methods.

counter.get(); // 0
counter.set( 3 );
counter.increment(); // 4
counter.increment(); // 5

If we attempt to access counter.i from the global environment, it will be undefined as it is enclosed within the invoked function and is not a property of counter. Likewise, if we attempt to access i it will result in an error as we have not declared i in the global environment.

术语[编辑]

"Immediately-invoked function expression" as a term describes a design pattern which has also been referred to as a "self-executing anonymous function."[1][5] However, immediately-invoked functions need not be anonymous and ECMAScript 5's strict mode forbids arguments.callee,[16] making the latter term less accurate.[3][12]

In lambda-calculus, this construct was referred to as "redex", for reducible expression, see Reduction strategy (code optimization).

参考[编辑]

  1. ^ 1.0 1.1 1.2 1.3 Alman, Ben. Immediately Invoked Function Expressions. 2010 [4 February 2013]. 
  2. ^ Resig, John. Pro JavaScript Techniques. Apress. 2006: 29. ISBN 9781430202837. 
  3. ^ 3.0 3.1 Osmani, Addy. Learning JavaScript Design Patterns. O'Reilly. 2012: 206. ISBN 9781449334871. 
  4. ^ Baagoe, Johannes. Closing parenthesis in function's definition followed by its call. [19 April 2010]. 
  5. ^ 5.0 5.1 Lindley, Cody. JavaScript Enlightenment. O'Reilly. 2013: 61. ISBN 9781449342883. 
  6. ^ Zakas, Nicholas. Maintainable JavaScript. O'Reilly. 2012: 44. ISBN 9781449327682. 
  7. ^ Crockford, Douglas. Code Conventions for the JavaScript Programming Language. [3 February 2013]. 
  8. ^ "JavaScript Semicolon Insertion: Everything you need to know", Friday, May 28, 2010
  9. ^ "Semicolons in JavaScript are optional", by Mislav Marohnić, 07 May 2010
  10. ^ Haverbeke, Marijn. Eloquent JavaScript. No Starch Press. 2011: 29–30. ISBN 9781593272821. 
  11. ^ Alman, Ben. simple-iife-example.js. Github. [5 February 2013]. 
  12. ^ 12.0 12.1 Otero, Cesar; Larsen, Rob. Professional jQuery. John Wiley & Sons. 2012: 31. ISBN 9781118222119. 
  13. ^ Herman, David. Effective Javascript. Addison-Wesley. 2012: 44–45. ISBN 9780321812186. 
  14. ^ Zakas, Nicholas C. Mimicking Block Scope. Professional JavaScript for Web Developers. John Wiley & Sons. 2011. ISBN 9781118233092. 
  15. ^ Rettig, Pascal. Professional HTML5 Mobile Game Development. John Wiley & Sons. 2012: 145. ISBN 9781118301333. 
  16. ^ Strict mode. Mozilla JavaScript Reference. Mozilla Developer Network. [4 February 2013]. 

外部链接[编辑]