js的方法中,this对象是运行时确定的,它指向的是调用者,如果通过new 操作符创建的方法对象,this指向方法对象本身。
但很多时候这个this对象不是我们所期望的this对象。所以,JS中提供了call,apply方法来改变函数中的this对象。后来呢,又提供了一个bind方法,不只能改变this对象,还能绑定一些参数。
call,apply,bind方法的作用都是改变函数中的this对象,call,apply调用时会改变this对象并且执行。而bind方法调用时会在原函数上进行赋值,返回一个包装的函数,这个函数的this对象绑定为给定的对象。我觉得,使用bind方法来实现js中模拟继承的功能更方便。
计算机语言还是看代码理解的块,文字只能让人越看越迷糊。上代码:
var squre="我是一个形状"; function polygon(x,y){ console.log((this.squre||"我不知道是什么")+"。位置在"+x+","+y); } new polygon(10,10); polygon(15,15); polygon.call({squre:"我是一个三角形"},20,20); polygon.apply({squre:"我是一个矩形"},[40,40]); var star=polygon.bind({squre:"我是一个星形"},50); star(60); new star(80);
运行结果如下:
通过new操作符创建的polygon对象,this指向的是他本身,它本身是没有squre属性的,所以打印“我不知道是什么”。
直接调用polygon,this对象指向他的调用者,也就是global的window对象,而window对象中,我们通过var定义了squre属性,所以打印“我是一个形状”。
通过call,apply调用时传入的对象会作为this对象,所以打印“我是一个三角形”和“我是一个矩形”。call,apply的不同之处就在于参数的传递,call传递参数是一个一个的传递的,而apply传递参数是通过一个数组传递的。使用哪个要根据的你要传递的参数来决定。
通过bind调用返回了一个star函数,这个函数绑定了传入的对象作为this对象,并且捎带着传入了50作为x值,当然这个不是必须的,你也可以不传。直接调用star方法,this并没有指向调用者,而是绑定的传入对象。但是通过new操作符来调用这个bind返回的函数时,这个传入的绑定对象作为this将会被忽略,而会用star函数自己作为this对象,虽然this不起作用了,但是bind传入的参数还是起作用的。
bind方法理解相对比较容易,当然是在你对call和apply方法理解的前提下。bind绑定this对象,还可以简单的使用在setTimeout的定时器调用时:
var div=document.getElementById("div1"); div.onclick=function(){ setTimeout(move.bind(this),1000); } function move(){ var rect=this.getBoundingClientRect(); this.style.left=(rect.left+100)+"px"; this.style.top=(rect.top+100)+"px"; }
通过bind绑定,在move方法中就可以获取到dom元素了。
bind方法是通过Function.prototype.bind定义的。它在IE9+的浏览器上获得了支持,在一定程度上,我们是可以大胆使用bind方法的。尤其是在移动端页面中,使用bind更加没有顾虑。