1.其实js中的this没那么难理解,当找不到this时记住一句话:
谁调我,我就指谁!new 谁指谁数组
function text1(){ console.log(this); //指window由于是window调我了 } var text2={ one:function(){ console.log(this); //指text由于text调我,我就指它! } } function text3(){ this.x=this; } var t=new text3(); t.x; //指text3 new 谁指谁
2.apply和call两个方法的做用都是改变this的指向
来个栗子:app
function food(){} food.prototype={ color:"red", name:'apple', sayName:function(){ console.log('my name is '+this.name); } } var text1=new food(); text1.sayName();//my name is apple var banana={ name:'banana' } var pear={ name:'pear' } text1.sayName.apply(banana); //my name is banana text1.sayName.call(pear); //my name is pear
apply与call的做用彻底同样就是接收参数的方式不一样列如:函数
var fn=function(arg1,arg2){} apply(fn,[arg1,arg2]); call(fn,arg1,arg2);
那么当参数,数量固定的时候用call不固定时用apply
这里特别说下函数内的arguments对象他是一个伪数组不能直接使用push等方法
下面写几个栗子展现下他两的实际用法:this
//第一个栗子追加数组 var array1=[1,2,3,4,5]; var array2=[6,7,8,9,10]; Array.prototype.push.apply(array1,array2); array1; //[1,2,3,4,5,6,7,8,9,10]
//第二个栗子求number的最大值 var numbers=[1,10,33,100,-55,423]; Math.max.apply(Math,numbers); Math.max.call(Math,1,10,33,100,-55,423);
//来个常常用到的代理console.log方法 function log(msg){ console.log(msg); } //上面是经常使用的写法,但这样 我传的值是 log(1) 没毛病 若是是log(1,2,3)呢?那就有毛病了 //他无论后面传多少参数都会被舍弃掉只会打印1 //改进版本 function log(){ console.log.apply(console,arguments); } //这样无论传多少个参数都能打印出来了
bind() 方法与 apply 和 call 很类似,也是能够改变函数体内 this 的指向。prototype
概念是:bind()方法会建立一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以建立它时传入 bind()方法的第一个参数做为 this,传入 bind() 方法的第二个以及之后的参数加上绑定函数运行时自己的参数按照顺序做为原函数的参数来调用原函数。代理
var say=function(){ console.log(this.x) } var one={ x:1 } var two={ x:2 } var three={ y:3 } var fn=say.bind(one); fn()//1 var fn2=say.bind(two).bind(one).bind(three);//若是连续bind呢?结果会是什么? fn2();//结果仍是第一个bind
缘由是,在Javascript中,屡次 bind() 是无效的。更深层次的缘由, bind() 的实现,至关于使用函数在内部包了一个 call / apply ,第二次 bind() 至关于再包住第一次 bind() ,故第二次之后的 bind 是没法生效的。
那么call、apply、bind三者之间的区别和应用场景是什么呢?code
var obj={ x:81 } var text={ fn:function(){ return this.x; } } console.log(text.fn.call(obj));//81 console.log(text.fn.apply(obj));//81 console.log(text.fn.bind(obj)());//81
结果都是81,但注意的是bind()后面多了对调用的括号。
那么总结一下:对象
apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;three
apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;ip
apply 、 call 、bind 三者均可以利用后续参数传参;
bind 是返回对应函数,便于稍后调用;apply 、call 则是当即调用 。