JavaScript中的每一个Function对象都有一个apply()方法、bind()方法和一个call()方法,它们的语法分别为:
bind()--也是改变函数体内this的指向;
bind会创建一个新函数,称为绑定函数,当调用这个函数的时候,绑定函数会以创建它时传入bind()方法的第一个参数作为this,传入bind()方法的第二个及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数;
bind与apply、call最大的区别就是:bind不会立即调用,其他两个会立即调用
一、call() 和apply()
apply和call都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部this的指向),将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象”。;如果使用apply或call方法,那么this指向他们的第一个参数,apply的第二个参数是一个参数数组
call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法。
apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即A对象应用B对象的方法。
var obj = { name: 'derrick' }; function fn(num1, num2) { console.log(num1 + num2); console.log(this); } fn(100, 200); // this -> window, num1 =100, num2 = 200 fn.call(100, 200); // this -> 100, num1 = 200, num2 = undefined fn.call(obj, 100, 200); // this -> obj, num1 = 100, num2 = 200 fn.call(); // this -> window,在严格模式下 this -> undefined fn.call(null); // this -> window,在严格模式下 this -> null fn.call(undefined);
1、 实现继承
function Animal(name){ this.name = name; this.showName = function(){ alert(this.name); } } function Cat(name){ Animal.apply(this,[name]); } var cat = new Cat("咕咕"); cat.showName(); /*call的用法*/ Animal.call(this,name);
2、
function Class10(){ this.showSub = function(a,b){ alert(a - b); } } function Class11(){ this.showAdd = function(a,b){ alert(a + b); } } function Class12(){ Class10.apply(this); Class11.apply(this); // Class10.call(this); //Class11.call(this); } var c2 = new Class12(); c2.showSub(3,1); //2 c2.showAdd(3,1); //4
apply的一些其他巧妙用法
因为Math.max不支持Math.max([param1,param2])也就是数组,但是它支持Math.max(param1,param2...),所以可以根据apply的特点来解决 var max=Math.max.apply(null,array),这样就轻易的可以得到一个数组中的最大项(apply会将一个数组转换为一个参数接一个参
数的方式传递给方法)
Array.prototype.push可以实现两个数组的合并
var a1=new Array("1","2","3"); var a2=new Array("4","5","6"); Array.prototype.push.apply(a1,a2); //得到合并后数组的长度,因为push就是返回一个数组的长度
通常在什么情况下,可以使用apply类似Math.max等之类的特殊用法:
一般在目标函数只需要n个参数列表,而不接收一个数组的形式,可以通过apply的方式巧妙地解决这个问题。
三、bind()这个方法在IE6-8下不兼容
fn.call(obj, 1, 2); // -> 改变this和执行fn是一起且都完成的 fn.bind(obj, 1, 2); // -> 只是改变了fn中的this为obj,并且给fn传递了两个参数值1, 2; // 但是此时并没有把fn这个函数执行;执行bind会有一个返回值,这个返回值tempFn就是把fn的 // this改变后的那个结果 // -> 预处理: 事先把fn的this改变为自己想要的结果,并且把对应的参数值,以后要用到了, // 直接的执行即可。 var tempFn = fn.bind(obj, 1, 2); tempFn(); // 输出和 fn.call(obj, 1, 2); 一致