javascript-this,call,apply,bind简述3
上节介绍了call()和apply()的用法,这节再讨论一下arguments参数和bind函数的用法以及函数柯里化就算是完结了。
bind()函数
先看定义:
bind()方法会创建一个函数的实例,其this值会被绑定到传给bind()函数的值。代码如下:
1 var name="window"; 2 var obj={ 3 name:"obj对象" 4 }; 5 6 7 function sayName(){ 8 9 console.log(this.name) 10 }; 11 12 var bindSayName = sayName.bind(obj); 13 14 bindSayName(); //obj对象
由代码可以看出,call()函数会直接调用,而bind()函数则是先生成,再通过其他途径来调用,但是this指针不会再发生改变。
arguments
函数体内可以通过arguments对象来访问参数数组,从而获得传递给函数的每一个参数。
1 function fn (x,y,z) { 2 arguments.length; //2 3 arguments[0]; //1 4 arguments[0]=10; 5 console.log(x); //10 6 7 arguments[2]=100; 8 console.log(z) //undefined 9 10 arguments.callee ===fn //true 11 } 12 13 fn(1,2);
使用arguments来获得函数参数时,arguments需要和参数之间存在绑定关系,如4,5行是可以修改成功的,但7,8行是没有绑定关系的,因为并没有一开始传递z这个参数进来。(4,5行在严格模式下参数也是不会变化的)
arguments对象的长度是由传入的参数个数决定的,不是由定义函数时的命名参数的个数决定。
函数currying化
即把函数拆分成多个单元。比如:
1 function add(a,b,c) { 2 return a+b+c; 3 } 4 5 var fun1 = add.bind(undefined,100); 6 fun1(1,2); //103 7 8 var fun2 = fun1.bind(undefined,200); 9 fun2(10); //310
5,6行表示给add函数绑定了一个undefined(相当于window),并传递了一个参数100,则100会首先赋值给add函数的参数a,然后执行fun1,b和c分别赋值为1,2,得到103。8,9行再在fun1的基础上绑定参数200,这时200会传递给参数b,因为a已经绑定为100,然后传入c=10,得到310。
柯里化的好处
1 function getConfig (colors,size,other) { 2 console.log(colors,size,other); 3 } 4 5 var defaultConfig = getConfig.bind(undefined,"#000","1024*768"); 6 7 defaultConfig("嘿嘿"); //#000 1024*768 嘿嘿 8 defaultConfig("呵呵"); //#000 1024*768 呵呵
可以看出来,第五行可以只传入两个参数,第七行和第八行分别再传入other参数,colors和size参数则是公共的,这样可以大量减小代码冗余。
bind和new
1 function fn () { 2 this.a=100; 3 return this.b; 4 } 5 6 var fun1 = fn.bind({b:1}); 7 8 fun1(); //1 9 new fun1() //{a:100}
return后必须是个对象才会作为返回值,否则会返回this的值,this会指向无bind时的this指向,并返回所有的值。
bind方法的实现
1 if (!Function.prototype.bind) { 2 Function.prototype.bind = function(oThis) { 3 if (typeOf this!=='function') { 4 throw new Error('调用bind函数的对象不是function。') 5 }; 6 //函数实现 7 var aArgs= Array.prototype.slice.call(arguments,1), 8 fToBind=this, 9 fNOP = function(){}, 10 fBound = function () { 11 return fToBind.apply(this instance fNOP?this:oThis, 12 aArgs.concat(Array.prototype.slice.call(arguments))) 13 }; 14 fNOP.prototype = this.prototype; 15 fBound.prototype = new fNOP(); 16 return fBound; 17 }; 18 };
bind方法的实现还是比较绕的,等研究完原型链有关的内容再回头做这段代码的介绍。