学院网站建设项目范围变更申请表,工业设计公司怎么收费,工业智能科技网站设计,wordpress下载视频教程文中内容均来自于曾探《JavaScript设计模式与开发实践》的学习笔记。闭包作用域变量的作用域#xff0c;就是指变量的有效范围。局部变量、全局变量。变量的搜索是从内到外而非从外到内的。变量的生命周期对于全局变量莱索#xff0c;全局变量的生命周期是永久的#xff0c;…文中内容均来自于曾探《JavaScript设计模式与开发实践》的学习笔记。闭包作用域变量的作用域就是指变量的有效范围。局部变量、全局变量。变量的搜索是从内到外而非从外到内的。变量的生命周期对于全局变量莱索全局变量的生命周期是永久的除非我们主动销毁这个全局变量。而对于函数内用var关键字生命的局部变量来说当退出函数时这些局部变量即失去了它们的价值它们会随着函数调用的结束而被销毁。闭包f返回了一个匿名函数的应用它可以访问到func()被调用时产生的环境而局部变量a一直处于这个环境中所以不会被销毁。局部变量的生命周期看起来被延续了。 //现在来看看下面这段代码 varfuncfunction(){ vara1; returnfunction(){ a; alert ( a ); } }; varffunc(); f(); // 输出2 f(); // 输出3 f(); // 输出4 f(); // 输出5!DOCTYPE htmlhtml langenhead meta charsetUTF-8 titleDocument/title/headbody div1111111111111/div div2/div div3/div div4/div div5/div script typetext/javascript var nodes document.getElementsByTagName(div); // 方法一 for (let i 0; i nodes.length; i) { nodes[i].onclick function(){ alert(i) } } // 方法二 // for (var i 0; i nodes.length; i) { // (function(a){ // nodes[a].onclick function(){ // alert(a) // } // })(i) // } // 方法三 // for (var i 0; i nodes.length; i) { // nodes[i].onclick (() { // var a i; // return () { // alert(a); // } // })(); // } /script/body/html闭包的作用封装数据闭包可以把一些不需要暴露在全局的变量封装成“私有变量”。 //最好是把它们用闭包封闭起来。代码如下 var mult (function(){ var cache {}; var calculate function(){ // 封闭calculate 函数 var a 1; for ( var i 0, l arguments.length; i l; i ){ a a * arguments[i]; } return a; }; return function(){ var args Array.prototype.join.call( arguments, , ); if ( args in cache ){ return cache[ args ]; } return cache[ args ] calculate.apply( null, arguments ); } })();延续局部变量的寿命 //现在我们把img 变量用闭包封闭起来便能解决请求丢失的问题 var report (function(){ var imgs []; return function( src ){ var img new Image(); imgs.push( img ); img.src src; } })();闭包和面向对象设计过程和数据的结合是形容面向对象中的“对象”时经常使用的表达。对象以方法的形式包含了过程而闭包则是在过程中以环境的形式包含了数据。通常用面向对象思想能实现的功能用闭包也能实现。 //下面来看看这段跟闭包相关的代码 var extent function(){ var value 0; return { call: function(){ value; console.log( value ); } } }; var extent extent(); extent.call(); // 输出1 extent.call(); // 输出2 extent.call(); // 输出3 //如果换成面向对象的写法就是 var extent { value: 0, call: function(){ this.value; console.log( this.value ); } }; extent.call(); // 输出1 extent.call(); // 输出2 extent.call(); // 输出3 //或者 var Extent function(){ this.value 0; }; Extent.prototype.call function(){ this.value; console.log( this.value ); }; var extent new Extent(); extent.call(); extent.call(); extent.call();用闭包实现命令模式命令接受者会被封闭再闭包形成的环境中。script typetext/javascript var Tv { open: function(){ console.log( 打开电视机 ); }, close: function(){ console.log( 关上电视机 ); } }; var createCommand function( receiver ){ var execute function(){ return receiver.open(); // 执行命令打开电视机 } var undo function(){ return receiver.close(); // 执行命令关闭电视机 } return { execute: execute, undo: undo } }; var setCommand function( command ){ document.getElementById( execute ).onclick function(){ command.execute(); // 输出打开电视机 } document.getElementById( undo ).onclick function(){ command.undo(); // 输出关闭电视机 } }; setCommand( createCommand( Tv ) );/script闭包和内存泄露内存泄露的原因闭包不是罪魁祸首全局作用域和闭包对内存方便的影响是一样的并不能说是内存泄露。是BOM和DOM引起的如果两个对象之间形成了循环引用那么这两个对象都无法被回收。解决方法手动将变量设为null。高阶函数高阶函数是指至少满足下列条件之一的函数函数可以作为参数被传递函数可以作为返回值输出函数作为参数传递回调函数 var getUserInfo function( userId, callback ){ $.ajax( http://xxx.com/getUserInfo? userId, function( data ){ if ( typeof callback function ){ callback( data ); } }); } getUserInfo( 13157, function( data ){ alert ( data.userName ); });Array.prototype.sort [ 1, 4, 3 ].sort( function( a, b ){ return a - b; });函数作为返回值输出判断数据的类型 //我们还可以用循环语句来批量注册这些isType 函数 var Type {}; for ( var i 0, type; type [ String, Array, Number ][ i ]; ){ (function( type ){ Type[ is type ] function( obj ){ return Object.prototype.toString.call( obj ) [object type ]; } })( type ) }; Type.isArray( [] ); // 输出true Type.isString( str ); // 输出true单例模式 var getSingle function ( fn ) { var ret; return function () { return ret || ( ret fn.apply( this, arguments ) ); }; };高阶函数实现AOPAOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来这些跟业务逻辑无关的功能通常包括日志统计、安全控制、异常处理等。 Function.prototype.before function( beforefn ){ var __self this; // 保存原函数的引用 return function(){ // 返回包含了原函数和新函数的代理函数 beforefn.apply( this, arguments ); // 执行新函数修正this return __self.apply( this, arguments ); // 执行原函数 } }; Function.prototype.after function( afterfn ){ var __self this; return function(){ var ret __self.apply( this, arguments ); afterfn.apply( this, arguments ); return ret; } }; var func function(){ console.log( 2 ); }; func func.before(function(){ console.log( 1 ); }).after(function(){ console.log( 3 ); }); func();高阶函数的应用currying函数柯里化又称部分求值一个currying的函数首先会接受一些参数接收了这些参数之后该函数并不会立刻求值而是继续返回另外一个函数刚才传入的函数在函数形成的闭包中被保存起来。待到函数被真正需要求值的时候之前传入的所有参数都会被一次性用于求值。 var currying function( fn ){ var args []; return function(){ if ( arguments.length 0 ){ return fn.apply( this, args ); }else{ [].push.apply( args, arguments ); return arguments.callee; } } }; var cost (function(){ var money 0; return function(){ for ( var i 0, l arguments.length; i l; i ){ money arguments[ i ]; } return money; } })(); var cost currying( cost ); // 转化成currying 函数 cost( 100 ); // 未真正求值 cost( 200 ); // 未真正求值 cost( 300 ); // 未真正求值 alert ( cost() ); // 求值并输出600uncurrying一个对象未必只能使用它自身的方法可以使用别的对象的方法比如call和apply就能实现。 Function.prototype.uncurrying function () { var self this; return function() { var obj Array.prototype.shift.call( arguments ); return self.apply( obj, arguments ); }; }; var push Array.prototype.push.uncurrying(); (function(){ push( arguments, 4 ); console.log( arguments ); // 输出[1, 2, 3, 4] })( 1, 2, 3 );函数节流场景比如window.resize事件mousemove事件上传进度原理指定时间间隔内只会执行一次任务。将即将被执行的函数用setTimeout延迟一段时间执行。如果该次延迟执行还没有完成则忽略接下来的调用该函数的请求。实现 var throttle function ( fn, interval ) { var __self fn, // 保存需要被延迟执行的函数引用 timer, // 定时器 firstTime true; // 是否是第一次调用 return function () { var args arguments, __me this; if ( firstTime ) { // 如果是第一次调用不需延迟执行 __self.apply(__me, args); return firstTime false; } if ( timer ) { // 如果定时器还在说明前一次延迟执行还没有完成 return false; timer setTimeout(function () { // 延迟一段时间执行 clearTimeout(timer); timer null; __self.apply(__me, args); }, interval || 500 ); }; };防抖场景用户名输入后判断用户是否存在原理任务频繁触发的情况下只有任务触发的间隔超过指定间隔的时候任务才会执行。分时函数 var timeChunk function( ary, fn, count ){ var obj, t; var len ary.length; var start function(){ for ( var i 0; i Math.min( count || 1, ary.length ); i ){ var obj ary.shift(); fn( obj ); } }; return function(){ t setInterval(function(){ if ( ary.length 0 ){ // 如果全部节点都已经被创建好 return clearInterval( t ); } start(); }, 200 ); // 分批执行的时间间隔也可以用参数的形式传入 }; }; var ary []; for ( var i 1; i 1000; i ){ ary.push( i ); }; var renderFriendList timeChunk( ary, function( n ){ var div document.createElement( div ); div.innerHTML n; document.body.appendChild( div ); }, 8 ); renderFriendList();惰性加载函数html body div iddiv1点我绑定事件/div script var addEvent function( elem, type, handler ){ if ( window.addEventListener ){ addEvent function( elem, type, handler ){ elem.addEventListener( type, handler, false ); } }else if ( window.attachEvent ){ addEvent function( elem, type, handler ){ elem.attachEvent( on type, handler ); } } addEvent( elem, type, handler ); }; var div document.getElementById( div1 ); addEvent( div, click, function(){ alert (1); }); addEvent( div, click, function(){ alert (2); }); /script /body/html总结很多模式都是通过闭包和高阶函数实现的。相对于模式的实现过程我们更关注的是模式可以帮助我们完成什么