1.函数做为形参传递
2.函数做为返回值输出javascript
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'; });
Array.prototype.sort 接受一个函数看成参数,这个函数里面封装了数组元素的排序规则。从Array.prototype.sort 的使用能够看到,咱们的目的是对数组进行排序,这是不变的部分;而使用什么规则去排序,则是可变的部分。把可变的部分封装在函数参数里,动态传入
Array.prototype.sort,使 Array.prototype.sort 方法成为了一个很是灵活的方法。html
let arr = [2,1,3]; arr.sort((a,b)=>{ return a - b; //a-b 从小到大,b-a 从大到小 }) console.log(arr); //[1,2,3]
var getSingle = function ( fn ) { var ret; return function () { return ret || ( ret = fn.apply( this, arguments ) ); }; }; //这个高阶函数的例子,既把函数看成参数传递,又让函数执行后返回了另一个函数。咱们 //能够看看 getSingle 函数的效果: var getScript = getSingle(function(){ return document.createElement( 'script' ); }); var script1 = getScript(); var script2 = getScript(); alert ( script1 === script2 ); // 输出:true
AOP(面向切面编程)的主要做用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些跟业务逻辑无关的功能一般包括日志统计、安全控制、异常处理等。把这些功能抽离出来以后,再经过“动态织入”的方式掺入业务逻辑模块中。这样作的好处首先是能够保持业务逻辑模块的纯净和高内聚性,其次是能够很方便地复用日志统计等功能模块一般,在 JavaScript 中实现 AOP,都是指把一个函数“动态织入”到另一个函数之中,具体的实现技术有不少,本节咱们经过扩展 Function.prototype 来作到这一点。代码以下:java
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();//1 2 3
currying 又称部分求值。一个 currying 的函数首先会接受一些参数,接受了这些参数以后,该函数并不会当即求值,而是继续返回另一个函数,刚才传入的参数在函数造成的闭包中被保存起来。待到函数被真正须要求值的时候,以前传入的全部参数都会被一次性用于求值。node
var cost = (function(){ var args = []; return function(){ if ( arguments.length === 0 ){ var money = 0; for ( var i = 0, l = args.length; i < l; i++ ){ money += args[ i ]; } return money; }else{ [].push.apply( args, arguments ); } } })(); cost( 100 ); // 未真正求值 cost( 200 ); // 未真正求值 cost( 300 ); // 未真正求值 console.log( cost() ); // 求值并输出:600
实现:经过闭包来实现
一个简单的例子:ajax
//节流 let jieliu = (function (){ let ajax = true; return function(){ console.log(ajax); if(ajax){ ajax = false; let time = setTimeout(function(){ ajax = true; console.log('ajaxing'); },5000); } } })(); document.getElementById('test').onclick = jieliu;
某些函数确实是用户主动调用的,但由于一些客观的缘由,这些函数会严重地影响页面性能在短期内往页面中大量添加 DOM 节点显然也会让浏览器吃不消,咱们看到的结果每每就是浏览器的卡顿甚至假死。代码以下:编程
var ary = []; for ( var i = 1; i <= 10000000; i++ ){ ary.push( i ); // 假设 ary 装载了 10000000 个好友的数据 }; var renderFriendList = function( data ){ for ( var i = 0, l = data.length; i < l; i++ ){ var div = document.createElement( 'div' ); div.innerHTML = i; document.body.appendChild( div ); } }; renderFriendList( ary ); //哈哈,界面直接提示崩溃啦
解决方案:分时函数 - 利用setTimeout 每隔一段时间建立dom节点加入界面中,缓解一次性添加过多dom结点形成的低性能问题设计模式
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 <= 10000000; i++ ){ ary.push( i ); }; var renderFriendList = timeChunk( ary, function( n ){ var div = document.createElement( 'div' ); div.innerHTML = n; document.body.appendChild( div ); }, 12 ); renderFriendList();
在 Web 开发中,由于浏览器之间的实现差别,一些嗅探工做老是不可避免。好比咱们须要一个在各个浏览器中可以通用的事件绑定函数 addEvent
新手写法:数组
var addEvent = function( elem, type, handler ){ if ( window.addEventListener ){ return elem.addEventListener( type, handler, false ); } if ( window.attachEvent ){ return elem.attachEvent( 'on' + type, handler ); } }; //缺点是当它每次被调用的时候都会执行里面的 if 条件分支,虽然执行这些 if分支的开销不算大,但也许有一些方法可让程序避免这些重复的执行过程。
进阶写法:浏览器
var addEvent = (function(){ if ( window.addEventListener ){ return function( elem, type, handler ){ elem.addEventListener( type, handler, false ); } } if ( window.attachEvent ){ return function( elem, type, handler ){ elem.attachEvent( 'on' + type, handler ); } } })(); //咱们把嗅探浏览器的操做提早到代码加载的时候,在代码加载的时候就马上进行一次判断,以便让 addEvent 返回一个包裹了正确逻辑的函数。
缺点:也许咱们从头至尾都没有使用过 addEvent 函数,这样看来,前一次的浏览器嗅探就是彻底多余的操做,并且这也会稍稍延长页面 ready 的时间。安全
老司机写法: - 惰性载入函数方案
<html> <body> <div id="div1">点我绑定事件</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>