什么是自执行和立即执行
下面
代码会出现语法错误,因为解释器会认为这个是函数声明,而不是表达式。
function NotAutoExecute(){
//dosomthing
}();
在
函数声明外加上括号
,转化为表达式,即可
立即执行
。
(function NotAutoExecute(){
//dosomthing
} )();
一般情况使用的是上述的自执行代码,这样可以将函数内容封装,不污染全局变量空间。注意下面的是严格一样上得自执行,自己调用自己,用得比较少。
(function AutoExecuteSelf(){
AutoExecuteSelf();
//dosomthing
})();
特点
- 地道的 JavaScript,威力强大;- 实现代码隐藏(JavaScript 中只有函数能创建作用域);
- 隔离(防止污染或污染别人,并且为变量取名称很杀脑细胞);
一些用途
- 为有大量临时变量的代码,创建一个作用域,防止命名冲突;- 防止作用域/第三方代码污染(许多库的代码最外层都被这样围了起来);
- 视觉上的分段(一些很长的函数化的代码中比较常见);
- 执行一些需要进行初始化操作的代码(比如应用启动、模块启动、一次性模块);
- 编译器代码输出,最有特征的是 CoffeeScript(文件级别,或 do、class 关键字) 和 Closure Compiler;
- 减少重复创建比较大的对象的开销(常见在一些工具函数内部,保存正则对象,数组,长字符串等对象);
- 实现状态、记忆或缓存;
- 达成一种代码组织风格,比如 YUI Module Pattern(实现私有成员)[3]、jQuery Widget Factory(注意全局对象及 undefined 参数的传递节省了变量定义) [4] 和 Ace Editor (节省了 prototype 对象的引用)[5];
- 实现 proxy pattern [6],在你想要拦截一个函数调用(常常是注入功能、改变路径、劫持或记录),同时又不想或不能修改其源代码时;
- 获取 global this 的一种方式;
- AMD exports 模板,大量库已经在使用了 [1];
- 特性探测模板(可返回具名函数做调试信息使用) [2];
一些样例
// 用闭包实现状态函数,最基础的结构之一
var nextId = function() {
var id = 1
return function() {
return id++
}
}()
// 浏览器特性探测
if (condition) Feature = (function() {
// code
return newImplOrDetected
})()
// 常量或对象属性初始化,特殊属性初始化(如需要取得函数定义期环境中的变量),或是键值对象初始化(如某些值之间存在关系,必需要运算才能得出)
object.prop = (function() {
var o = {}
o['__created__'] = Date.now()
o['name'] = object.otherProp
return o
})()
// 运行一次的模块
// modulerunner.js
(function() {
var module = require('module')
module.setup()
module.run()
})()
// 获取 global 对象,ES3 或 ES5 非严格模式
var getGlobalThis = function() {
return (function() { return this }).call(null)
}
// 工具函数
var f = (function() {
var cache = {}
// or
var complexRegex = /\d+/
// or
var bigObject = ['lg','gt','bull', 'nbsp']
return function() {
// impl
}
})()
// proxy pattern,根据条件改变路径
field.execCommand = function(proxied) {
return function(param) {
if (condition) {
handle(param)
} else {
proxied.apply(this, arguments)
}
}
}(field.execCommand)
<完>