函数是第一类对象 first-class object,能够做为带有属性和方法的值以及参数进行传递。 node
建立函数的语法 浏览器
function foo(){}; //函数声明 var bar=function(){}; //函数表达式 var baz=function baz(){};//函数命名表达式
//反模式 //仅用于掩饰 //全局函数 function foo(){ alert("global foo"); } function bar(){ alert("global bar"); } function hoisMe(){ console.log(typeof foo); //输出function console.log(typeof bar); //输出undefined foo(); //输出local foo bar(); //输出 TypeError: bar is not a function //函数声明 //变量 foo以其实现者被提高 function foo(){ alert("local foo"); } //函数表达式 //仅变量 bar被提高 //函数实现并未被提高 var bar=function(){ alert("local bar"); } } hoisMe();
//重构findNodes()以接受一个回调函数 var findNodes=function(callback){ var i=100000, nodes=[], found; if(typeof callback!=="function"){ callback=false; } while(i){ i-=1; // 这里是复杂的逻辑... //如今进行回调函数 if(callback){ callback(found); } nodes.push(found); } return nodes; } //回调函数 var hide=function(node){ node.style.display="none"; } //找到制定节点,并在后续执行中将其隐藏起来 findNodes(hide);
//传递一个匿名回调函数 findNodes(function(node){ node.style.display="block"; });
//重构findNodes()以接受一个回调函数 var findNodes=function(callback,callback_obj){ var i=100000, nodes=[], found; while(i){ i-=1; // 这里是复杂的逻辑... //如今进行回调函数 if(typeof callback==="string"){ callback=callback_obj[callback]; } if(typeof callback==="function"){ callback.call(callback_obj,found); } nodes.push(found); } return nodes; } //回调函数 var myapp={}; myapp.color="green"; myapp.paint=function(node){ node.style.color=this.color; }; //找到制定节点,并在后续执行中将其隐藏起来 findNodes(myapp.paint,myapp);
var setup=function(){ alert(1); return function(){ alert(2); } } //使用setup函数 var my=setup(); //alert1 my(); //alert 2
var setup=function(){ var count=0; return function(){ return (count+=1); } } //用法 var next=setup(); next(); //返回1 next(); //返回2 next(); //返回3
惰性函数定义 lazy function definition 缓存
var scareMe=function(){ alert("Boo!"); scareMe=function(){ alert("Double boo!"); } }; //使用自定义函数 scareMe(); //输出Boo! scareMe(); //输出Double boo!
var scareMe=function(){ alert("Boo!"); scareMe=function(){ alert("Double boo!"); } }; //1 .添加一个新的属性 scareMe.property="properly"; //2. 复制给另外一个不一样名称的变量 var prank=scareMe; //3. 做为一个方法使用 var spooky={ boo:scareMe }; //calling with a new name prank(); //输出 Boo! prank(); //输出 Boo! console.log(prank.property); //输出properly //做为一个方法来调用 spooky.boo(); //输出Boo! spooky.boo(); //输出Boo! console.log(spooky.boo.property); // 输出 properly //使用自定义函数 scareMe(); //输出 Double boo! scareMe(); //输出 Double boo! console.log(scareMe.property); //undefined
即时函数也叫自调用self-invoking 或者自执行self-executing函数。 闭包
即时函数中定义的变量将会用于它自身的局部变量,没必要担忧全局空间被临时的变量污染。 app
//定义模块module1 (function(){ //模块1中的全部代码 }());
本例子中即时函数的返回值是一个函数,它将分配给变量getResult,而且将简单地返回res值,该值被预计算并存储在即时函数的闭包中 ide
var getResult=(function(){ var res=2+2; return function(){ return res; } }());
定义对象属性时也可使用即时函数 函数
var o={ message:(function(){ var who="me", what="call"; return what + " "+who; }()), getMsg:function(){ return this.message; } }; //用法 console.log(o.getMsg()); //输出call me console.log(o.message); //输出call me
immediate object initalization 测试
({ //在这里能够定义设定值 //又名配置常数 maxwidth:600, maxheight:400, //还能够定义一些实用的方法 gimmeMax:function(){ return this.maxwidth+ "X" +this.maxheight; }, //初始化 init:function(){ console.log(this.gimmeMax()); //更多初始化任务。。。 } }).init();
init-time branching 也称为加载时分支 load-time branching 是一种优化模式 优化
//接口 var utils={ addListener:null, removeListener:null }; //实现 if(typeof window.addEventListener==="function"){ utils.addListener=function(el,type,fn){ el.addEventListener(type,fn,false); }; utils.removeListener=function(el,type,fn){ el.removeEventListener(type,fn,false); } }else if(typeof document.attachEvent==="function"){ //判断为IE浏览器 utils.addListener=function(el,type,fn){ el.attachEvent('on'+type,fn); }; utils.removeListener=function(el,type,fn){ el.detachEvent("on"+type,fn); }; }else{ //更早版本的浏览器 utils.addListener=function(el,type,fn){ el['on'+type]=fn; }; utils.removeListener=function(el,type,fn){ el['on'+type]=null; } }
对于每一个函数,它都会自动得到一个length属性,其中包含了该函数指望的参数数量。 this
function func(a,b,c,d){} console.log(func.length);
能够在任什么时候候将自定义属性添加到你的函数中。自定义属性的其中一个用例是缓存函数结果(即返回值),所以下次调用该函数时就不会重作潜在的繁重计算。 缓存函数结果也被称为备忘memoization
var myFunc=function(param){ if(!myFunc.cache[param]){ var result={}; //。。。开销很大的操做。。。 myFunc.cache[param]=result; } return myFunc.cache[param]; } //缓存存储 myFunc.cache={};
当须要传递大量参数时,一个更好的办法是仅使用一个参数对象来代替全部参数,该参数对象称为conf,也就是配置的意思。
var conf={ username:"lilu", first:"Yi", last:"Liu" } function addPerson(person){ return person.username +" " +person.first+" "+person.last; } addPerson(conf);
调用invoking函数和应用applying函数能够获得相同的结果
//定义函数 var sayHi=function(who){ return "Hello"+ (who?", "+who:"")+"!"; }; //调用函数 sayHi(); //输出Hello sayHi('world'); //输出Hello,World! //应用函数 sayHi.apply(null,['hello']); //输出Hello, hello!
//curry化的add()函数 //接受部分参数的列表 function add(x,y){ var oldx=x,oldy=y; if(typeof oldy==="undefined"){ //部分 return function(newy){ return oldx+newy; } } //彻底应用 return x+y; } //测试 typeof add(5); //输出function add(3)(4); //7 //建立病存储一个新函数 var add2000=add(2000); add2000(10);//输出2010
一个通用curry化函数
function schonfinkelize(fn){ var slice=Array.prototype.slice, stored_args=slice.call(arguments,1); return function(){ var new_args=slice.call(arguments), args=stored_args.concat(new_args); return fn.apply(null,args); } } //普通函数 function add(x,y){ return x+y; } //将一个函数curry化以得到一个新的函数 var newadd=schonfinkelize(add,5); newadd(4); //输出9 /另外一种选择——直接调用新函数 schonfinkelize(add,6)(7);
更多用法
//普通函数 function add(a,b,c,d,e){ return a+b+c+d+e; } //可运行于任意数量的参数 schonfinkelize(add,1,2,3)(5,5); //16 //两步curry化 var addOne=schonfinkelize(add,1); addOne(10,10,10,10); //输出41 var addSix=schonfinkelize(addOne,2,3); addSix(5,5); //输出16