立即执行函数, 及 immediately Invoked Function Express(IIFE), 正如它的名字, 就是创建函数的同时立即执行, 它没有绑定任何事件, 也无需等待任何异步操作:
- (function() {
- // 代码..
- })();
function(){...} 是一个匿名函数, 包围它的一对括号将其转换为一个表达式, 紧跟其后的一对括号调用了这个函数. 立即执行函数 也可以理解为立即调用一个匿名函数, 最常见的场景就是: 将 var 变量的作用域限制于函数内, 这样可以避免命名冲突
2. 闭包
对于闭包 (closure), 当外部函数返回之后, 内部函数依然可以访问外部函数的变量
- function f1() {
- var N = 0; // N 是 f1 的局部变量
- function f2() {
- // f2 是 f1 的内部函数, 闭包
- N += 1; // 内部函数 f2 中使用了外部函数 f1 中的变量 N
- console.log(N);
- }
- return f2;
- }
- var result = f1();
- result(); // 输出 1
- result(); // 输出 2
- result(); // 输出 3
代码中, 外部函数 f1 只执行了一次, 变量 N 设为 0, 并将内部函数 f2 赋值给了变量 result. 由于外部函数 f1 已经执行完毕, 其内部变量 N 应该在内存中被清除, 然后事实并不是这样: 我们每次调用 result 的时候, 发现变量 N 一直在内存中, 这就是闭包的神奇之处
3. 使用闭包定义私有变量
通常, JavaScript 开发者使用下划线作为私有变量的前缀, 但是实际上, 这些变量依然可以被访问和修改, 并非真正的私有变量, 这时, 使用闭包可以定义真正的私有变量:
- function Product() {
- var name;
- this.setName = function(value) {
- name = value;
- };
- this.getName = function() {
- return name;
- };
- }
- var P = new Product();
- P.setName("zhouJin");
- console.log(P.name); // undefined
- console.log(P.getName()); // zhouJin
代码中. 对象 P 的 name 属性为私有属性, 使用 p.name 不能直接访问
4.prototype
每个 JavaScript 构造函数都有一个 prototype 属性, 用于设置所有的实例对象需要共享的属性和方法, prototype 属性不能列举, JavaScript 仅支持通过 prototype 属性进行继承属性和方法
- function Rectangle(x, y) {
- this._length = x;
- this._breadth = y;
- }
- Rectangle.prototype.getDimensions = function() {
- return {
- length: this._length,
- breadth: this._breadth
- };
- };
- var a = new Rectangle(3, 4);
- var b = new Rectangle(4, 3);
- console.log(a.getDimensions()); // { length: 3, breadth: 4 }
- console.log(b.getDimensions()); // { length: 4, breadth: 3 }
代码中, a 和 b 都是构造函数 Rectangle 创建的对象实例, 它们通过 prototype 继承了 getDimensions 方法
5. 模块化
JavaScript 并非模块话编程语言, 至少 ES6 落地之前都不是, 然而对于一个复杂的 web 应用, 模块化编程时一个最基本的要求, 这时, 可以使用 立即执行 来实现模块化, 正如很多 JS 库比如 jQuery 都是这样实现的
- var module = (function() {
- var N = 5;
- function print(x) {
- console.log("the result is:" + x);
- }
- function add(a) {
- var x = a + N;
- print(x);
- }
- return {
- description: "This is description",
- add: add
- };
- })();
- console.log(module.description); // 输出 This is description
- module.add(5); // 输出 the result is:10
所谓模块化, 就是根据需要控制模块内属性与方法的可访问性, 即私有或者公开, 在代码中, module 为一个独立的模块, N 为其私有属性, print 为其私有方法, decription 为其公有属性, add 为其共有方法
6. 变量提升
JavaScript 会将所有变量和和函数声明移动到它的作用域前面, 这就是所谓的变量提升, 也就是说, 无论你在什么地方声明变量和函数, 解释器都会将他们移动到作用域的最前面, 因此我们可以先使用变量和函数, 而后声明它们,
但是, 仅仅变量声明被提升了, 而变量赋值不会被提示, 如果不明白这点有时则会报错
- console.log(y);
- // 输出 undefined
- y = 2;
- // 初始化 y
上面的代码等价于下面的代码
- var y;
- // 声明 y
- console.log(y);
- // 输出 undefined
- y = 2;
- // 初始化 y
为了避免 BUG, 开发者应该在每个作用域开始时声明变量和函数
来源: http://www.jianshu.com/p/891b17b5f6d8