立即执行函数 模拟块级作用域(私有作用域) 这是一种常用的写法(起手式),将匿名函数用括号括起来形成函数表达式 在该函数表达式后使用括号立即调用该函数表达式 前面的分号,是为了避免代码压缩后,前边的代码结尾没写分号。
使用立即执行函数 模拟出来的块级作用域,可以避免污染全局变量 而且还可以减少闭包占用的内存问题,因为没有指向匿名函数的引用, 只要函数执行完毕,就可以立即销毁其作用域了。
1 2 3 4 ;( function ( args ) { 'use strict' } )( args );
私有变量 静态私有变量 利用 构造函数的块级作用域 实现私有变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 function ObjName ( ) { var privateVariable = 10 ; function privateFunction (num ) { num++; return num; } this .publicMethod = function ( ) { privateVariable++; return privateFunction(privateVariable); }; this .getPrivateVariable = function ( ) { return PrivateVariable; } } var instance = new ObjName();instance.privateVariable; instance.privateFunction(); instance.getPrivateVariable(); instance.publicMethod(); var oo = new ObjName();oo.getPrivateVariable();
利用 立即执行函数的块级作用域 实现静态 私有变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 ;(function ( ) { var privateVariable = 10 ; function privateFunction (num ) { num++; return num; } ObjName = function ( ) {}; ObjName.prototype.publicMethod = function ( ) { privateVariable++; return privateFunction(privateVariable); }; ObjName.prototype.getPrivateVariable = function ( ) { return privateVariable; }; })(); var o = new ObjName();o.privateVariable; o.privateFunction(); o.getPrivateVariable(); o.publicMethod(); var oo = new ObjName();oo.getPrivateVariable();
由于公有函数定义在构造函数的原型对象上,所有实例将共享所有的私有成员。
单例模式与模块模式 JavaScript中,用对象字面量的方式实现单例模式:
1 2 3 4 5 6 7 var ObjName = { name : value, method : fucntion () { } };
在此基础上,声明私有变量、函数,并返回一个包含有私有变量、函数映射的匿名的公有单例对象就是模块模式了。
如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 var ObjName = function ( ) { var privateVariable = 10 ; function privateFunction ( ) { } return { getPrivateVariable : function ( ) { return privateVariable; }, publicMethod : function ( ) { privateVariable++; return privateFunction(); } } } var o = window .ObjName();o.getPrivateVariable(); o.publicMethod();
增强的模块模式 如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 var ObjName = function ( ) { var privateVariable = 10 ; function privateFunction ( ) { } var obj = new CustomType(); obj.publicVariable = 1 ; obj.publicMethod = function ( ) { privateVariable++; return privateFunction(); } return obj; } var o = window .ObjName();o.getPrivateVariable(); o.publicMethod();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ## 构造函数模式+原型模式实现自定义类型(类) ```js 'use strict' // define 定义 类 function ObjName( arg0,arg1,... ){ this.arg0 = arg0; this.arg1 = arg1; ... this.arr = ["value0","value1",...] ... } ObjName.prototype = { // 将constructor指针指回自身 保证 instanceof字符以及isPrototpeOf() 判断的正确性 constructor : ObjName, functionName : function(){ // do something }, functionName1 : function(){ // do something } ... } // use 使用 类实例 var instance = new ObjName( arg0,arg1,... ); var newArr = instance.arr; instance.functionName0(); ...
构造函数模式+动态原型模式实现自定义类型(类) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 'use strict' function ObjName ( arg0,arg1,... ) { this .arg0 = arg0; this .arg1 = arg1; ... this .arr = ["value0" ,"value1" ,...] ... if ( typeof this .functionName0 !== 'function' ){ ObjName.prototype.functionName0 = function ( ) { }; ObjName.prototype.functionName1 = function ( ) { }; ... } } var instance = new ObjName( arg0,arg1,... );var newArr = instance.arr;instance.functionName0(); ...
构造函数模式+原型模式实现继承(组合继承) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 'use strict' function SuperType ( arg0,arg1,... ) { this .arg0 = arg0; this .arg1 = arg1; ... this .arr = ["value0" ,"value1" ,...] } SuperType.prototype.superTypeFunctionName10 = function ( ) { } SuperType.prototype.superTypeFunctionName11 = function ( ) { } ... function SubTypeType ( arg0,arg1,arg2,... ) { SuperType.call( this ,arg0,arg1,... ); this .arg2 = arg2; } SubTypeType.prototype = new SuperType(); SubTypeType.prototype.constructor = SubTypeType; SubTypeType.prototype.SubTypeFunctionName0 = function ( ) { } SubTypeType.prototype.SubTypeFunctionName1 = function ( ) { } var instance = new SubTypeType( arg0,arg1,arg2,... );var newArr = instance.arr;instance.superTypeFunctionName10(); instance.SubTypeFunctionName0(); ...
由于组合式继承 调用了两次父类的构造函数,有稍稍稍微的内存损耗。 就有了如下 寄生组合式继承
构造函数模式+寄生动态原型模式实现继承(寄生组合式继承) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 'use strict' function inheritPrototype ( SubType, SuperType ) { var prototype = object( SuperType.prototype ); prototype.constructor = SubType; SubType.prototype = prototype; }; function SuperType ( arg0,... ) { this .arg0 = arg0; ... if ( typeof SuperType.prototype.superTypeFunctionName10 !== "function" ) { SuperType.prototype.superTypeFunctionName10 = function ( ) { }; SuperType.prototype.superTypeFunctionName11 = function ( ) { }; } } function SubTypeType ( arg0, arg1,... ) { SuperType.call( this , arg0 ); this .arg1 = arg1; if ( typeof SuperType.prototype.superTypeFunctionName10 !== "function" ) { SuperType.prototype.superTypeFunctionName10 = function ( ) { }; SuperType.prototype.superTypeFunctionName11 = function ( ) { }; } }; inheritPrototype( SubType, SuperType ); var instance = new Sub( arg0,arg1,... );instance.superTypeFunctionName10(); instance.superTypeFunctionName11();
函数表达式之递归 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 function factorial ( num ) { if ( num <= 1 ){ return 1 ; }else { return num * factorial( num - 1 ); } } var instance = factorial;factorial = null ; instance(4 ); function factorial ( num ) { if ( num <= 1 ){ return 1 ; }else { return num * arguments .callee( num - 1 ); } } var factorial = ( function f ( num ) { if ( num <= 1 ){ return 1 ; }else { return num * f( num - 1 ); } } );
闭包 函数中的函数称为闭包函数。
释放被闭包占用的内存 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function f ( arg0 ) { return function ( arg1 ) { return arg0 + arg1; } } var tem = f(3 );tem(5 ); tem = null ;
闭包只取得包含函数(或称外部函数)中任意变量的最后 一个值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 function f ( ) { var result = new Array (); var i; for ( i = 0 ; i < 10 ; i++ ){ result[i] = function ( ) { return i; }; } return result; } var fArr = f();fArr[0 ](); fArr[1 ](); ... fArr[8 ](); fArr[9 ]();
让函数return一个闭包函数,让这个函数数组中的函数的返回值符合预期。如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 function f ( ) { var result = new Array (); var i; for ( i = 0 ; i < 10 ; i++ ){ result[i] = function ( num ) { return function ( ) { return num; }; }( i ); } return result; } var fArr = f();fArr[0 ](); fArr[1 ](); ... fArr[8 ](); fArr[9 ]();
闭包中的 this关键字 在非严格模式 下将指向 window 对象 如下 “
1 2 3 4 5 6 7 8 9 10 11 12 13 var value = 'A' ;var Obj = { value :"B" , getValue : function ( ) { return function ( ) { return this .value; }; } } Obj.getValue()();
返回的是 A 而不是预期中的 B 因为闭包中的 this关键字 在非严格模式 下将指向 window 对象 而不是它包含函数(外部函数)作用域中的 Obj 对象。
在严格模式('use strict'
)下会报错:typeError: this is undefined
要想得到预期效果,必须将包含函数(外部函数)作用域中的 Obj 对象 以变量的形式的传入闭包函数的作用域中。如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 var value = 'A' ;var Obj = { value :"B" , getValue : function ( ) { var that = this ; return function ( ) { return that.value; }; } } Obj.getValue()(Obj);