1. var add = (function(){
    2. var counter = 0;
    3. return function(){
    4. return counter += 1;
    5. }
    6. })();
    7. add(); // 1
    8. add(); // 2
    9. add(); // 3
    10. console.log(add()); // 4

    闭包:
    闭包可以理解成定义在一个函数内部(或对象内部)的函数可以访问该函数内部的变量或方法,但是外部不能访问,这个函数内部的函数在外部有引用时,不会被回收机制回收,并且连父级函数一起常驻与内存中。它的作用是可以使得私有变量变成可能。

    函数的四种存在形式:
    1.函数形态形式

    1. var foo = function(){
    2. alert(this); // this === window
    3. }

    2.方法形态形式

    1. var o = {};
    2. o.foo = foo;
    3. o.foo(); // 弹出object
    4. var lib = {
    5. text:function(){
    6. alert(this); // 弹出object
    7. (function(){
    8. alert(this); // 此处匿名函数不属于lib对象所有this任然是window
    9. })()
    10. }
    11. }

    3.构造器形式

    1. var Person = function() {
    2. this.age = 19;
    3. this.name = 'Mr李'
    4. return {}; // 默认不写retrun的话,返回undefined或null
    5. }
    6. var p = new Person();
    7. alert(p.name); // undefined
    8. var Person = function() {
    9. this.age = 19;
    10. this.name = 'Mr李'
    11. return 123; // 非引用类型的话,使用new关键字return是对象的话使用对象,否则使用this
    12. }
    13. var p = new Person();
    14. alert(p.name); // 'Mr李'

    4.上下文调用模式

    1. var fool = function(a, b) {
    2. alert(this);
    3. return a > b ? a : b;
    4. }
    5. var mun = fool.apply(null, [112,114]); // 此时this为window
    6. var mun = fool.apply({}, [112,114]); // 此时this为{}
    7. var mun = fool.call(null, 112, 114); // 此时this为window
    8. var mun = fool.call({}, 112, 114); // 此时this为{}
    9. // apply与call就是参数列表不一样,其他功能一致
    10. // apply与call作用是改变this的指向,或用于继承
    11. function a(name, age) {
    12. this.name = name
    13. this.age = age;
    14. }
    15. function b(name,age, sex) {
    16. a.call(this, name, age);
    17. this.sex = sex;
    18. }
    19. var tempObj = new b('李俊扬', 18, '男');
    20. console.log(tempObj);

    函数模块化介绍:
    html:

    1. <script src="/asset/main.js" data-page="a"></script>

    JS:

    1. let script = doucument.script[doument.script.length];
    2. let pageName = script.getAttribute('data-page');
    3. if (pageName === 'a') {
    4. require(["./a.js"]);
    5. } else if (pageName === 'b') {
    6. requite(["./b.js"]);
    7. }

    一,原始写法, 缺点污染全局变量

    1. function m1 {
    2. // ...
    3. }
    4. function m2 {
    5. // ...
    6. }

    二,对象的写法,缺点是对外暴露所有成员,变量可以被外部修改

    1. var model1 = new Object({
    2. _count: 0,
    3. m1: function(){//...},
    4. m2: function(){//...},
    5. });

    三,立即执行函数,对外没有暴露私有成员,变量不可以被外部修改了

    1. var model1 = (function(){
    2. var _count = 0;
    3. var getCount = function(){//...};
    4. var setCount = function(){//...};
    5. return {
    6. getCount: getCount,
    7. setCount: setCount,
    8. }
    9. })();

    四,放大模式,模块太大,必须分几部分,或者一个模块继承另一个模块

    1. // 前提必须有一个jquery模块
    2. var jquery$ = (function(mod){
    3. mod.m1 = function(){//...};
    4. })(jquery)
    5. jquery$ = (function(mod){
    6. mod.m2 = function(){//...};
    7. })(jquery$)

    五,宽大模式,模块由网络加载无法知道那个模块先加载

    1. var jquery$ = (function(mod){
    2. mod.m1 = function(){//...};
    3. })(jquery || {})

    独立性是模块的重大的特点,模块内部最好不要与程序其他部分直接交互。为了在函数内部调用全局变量,必须显示的将变量输入

    1. var model = (function($, YAHOO){
    2. // ....
    3. })(jQuery, YAHOO);