许多模式都可以使用闭包和高阶函数来实现
闭包的形成与变量的作用域以及变量的生命周期密切相关
变量的作用域,就是指变量的有效范围。我们最常谈到的是在函数中声明的变量作用域。
在 JavaScript 中,函数可以用来创造函数作用域。此时的函数像一层半透明的玻璃,在函数里面可以看到外面的变量,而在函数外面则无法看到函数里面的变量。 这是因为当在函数中搜索一个变量的时候,如果该函数内并没有声明这个变量,那么此次搜索的过程会随着代码执行环境创建的作用域链往外层逐层搜索,一直搜索到全局对象为止。变量的搜索是从内到外而非从外到内的。点击事件为异步事件,在点击时循环已完毕,故每一个点击事件都会得到i = 5
method:使用闭包把每次循环的i值封闭起来
for (var i =0;i<5;i++){ (nodeArr[i].onclick = funcioton(){ alert(i) })(i) }也可使用es6 let。let声明封闭作用域
封装变量:闭包可以帮助把一些不需要暴露在全局的变量封装成”私有变量“
上面为最简易进行参数乘积的函数,接下来进行对代码提炼封装,以及闭包封装缓存
var mult = (function(){ var cahe = {} //封装功能函数,有助于代码复用性,用户计算不定个数入参乘积 var calculate = function(){ var a = 1 for (var i = 0,l=arguments.length;i<l;i++){ a = a*arguments[i] } return a } return function(){ // 将入参通过join连接成字符串作为object key存入缓存中,key部分可以扩展如 1,3,5 与3,1,5为同一结果 var args = [].join.call(arguments,',') //如果缓存过直接返回值 if(args in cache){ return cache[args] } //将未缓存加入缓存并返回 return cache[args] = calculate.apply(null,arguments) } })()延续局部变量的寿命
img 对象经常用于进行数据上报,如下所示:
var report = function( src ){ var img = new Image(); img.src = src; }; report( 'http://xxx.com/getUserInfo' );在这些浏览器下使用 report 函数进行数据上报会丢失 30%左右的数据,也就是说,report 函数并不是每一次都成功发起了 HTTP 请求。丢失数据的原因是 img 是 report 函数中的局部变量,当 report 函数的调用结束后,img 局部变量随即被销毁,而此时或许还没来得及发出 HTTP 请求,所以此次请求就会丢失掉。
现在我们把 img 变量用闭包封闭起来,便能解决请求丢失的问题:
var report = (function(){ var imgs = []; return function( src ){ var img = new Image(); imgs.push( img ); img.src = src; } })();高阶函数至少满足以下一个条件
函数可以作为参数被传递函数可以作为返回值输出回调函数
在ajax异步请求中,回调函数使用频繁。当我们想在ajax请求返回后做一些事情,最常见的方法使把callback函数当作参数传入发起ajax请求的方法中用于将逻辑代码抽离
var appendDiv = function( callback ){ for ( var i = 0; i < 100; i++ ){ var div = document.createElement( 'div' ); div.innerHTML = i; document.body.appendChild( div ); if ( typeof callback === 'function' ){ callback( div ); } } }; appendDiv(function( node ){ node.style.display = 'none'; });可以看到,隐藏节点的请求实际上是由客户发起的,但是客户并不知道节点什么时候会创建好,于是把隐藏节点的逻辑放在回调函数中,“委托”给 appendDiv 方法。appendDiv 方法当然知道节点什么时候创建好,所以在节点创建好的时候,appendDiv 会执行之前客户传入的回调函数。
3.Array.prototype.sort方法传入一个回调作为排序的规则,使sort成为一个非常灵活的方法
将函数作为返回值出,更能体现函数式编程的巧妙。让函数返回一个可执行的函数,意味着运算过程使可延续的
判断数据类型
用 Object.prototype.toString 来计算。Object.prototype.toString.call( obj )返回一个字符串,比如 Object.prototype.toString.call( [1,2,3] ) 总是返回 “[object Array]” , 而Object.prototype.toString.call( “str”)总是返回"[object String]"。
//通过return一个函数接收外部函数传入的参数,进行参数的嵌套, var isType = function( type ){ return function( obj ){ return Object.prototype.toString.call( obj ) === '[object '+ type +']'; } }; //接收第一个参数赋值不同类别的判断器 var isString = isType( 'String' ); var isArray = isType( 'Array' ); var isNumber = isType( 'Number' ); //接收第二个参数进行运算 console.log( isArray( [ 1, 2, 3 ] ) );