js中call和apply和bind详解
这几个主要是控制this的,因为javascript的this实在太野了,这个代码带来了极大的灵活性,但是也给编程者带来了很多麻烦~~不说废话了
一、call方法
call方法的完整格式:
func.call(thisV,arg1,arg2......); //函数的call方法,可以指定该函数内部this的指向(也就是函数执行时所在的作用域),然后在所指定的作用域,调用该函数
还是看一个例子吧,比较清晰明了
var obj = { name : 'winclpt' }; var obj1 = { name : 'phermis', f : function(p){ alert(this.name+' '+p); } } //obj1.f('hi'); 弹出phermis hi //obj1.f.call(obj,'hi'); 弹出winclpt hi
通过f函数的call方法我们将他的上下文环境转到了obj,并执行了它,此时获取到的name就是winclpt了,而不是原来的phermis
call方法的一个应用是调用对象的原生方法:避免对象中又覆盖了原生方法
二、apply方法
apply方法的作用和call方法类似,也是改变this指向,然后再调用该函数。
唯一区别就是,他接收一个数组作为函数执行时的参数,格式如下:
func.apply(thisV, [arg1, arg2, ...])
apply方法的第一个参数也是this所要指向的那个对象,如果设为null或undefined,则等同于指定全局对象。原函数的参数,在call方法中必须一个个添加,但是在apply方法中,必须以数组形式添加。
依旧我们看一个例子来理解一下:
function f(x,y){ alert(x+y); } f.call(null,1,1) // 2 f.apply(null,[1,1]) // 2
apply的一些应用
(1)找出数组中的最大元素
javascript不提供找出数组最大元素的函数。结合apply和Math.max可以做到
var array = [10,3,53,1,99,7]; Math.max.apply(null,array);//得到最大值99 //Math.max()的参数是10,3,53,1,99,7这样的 //apply的第二个参数刚好需要一个数组
(2)将数组的空元素变成undefined
通过apply方法,利用Array构造函数将数组的空元素变成undefined
Array.apply(null, ["a",,"b"]) // [ 'a', undefined, 'b' ]
空元素与undefined的差别在于,数组的foreach方法会跳过空元素,但是不会跳过undefined。因此,遍历内部元素的时候,会得到不同的结果。
(3)转换类似数组的对象为数组
另外,利用数组对象的slice方法,可以将一个类似数组的对象(比如arguments对象)转为真正的数组。
Array.prototype.slice.apply({0:1,length:1})
// [1]
Array.prototype.slice.apply({0:1})
// []
Array.prototype.slice.apply({0:1,length:2})
// [1, undefined]
Array.prototype.slice.apply({length:1})
// [undefined]
上面代码的apply方法的参数都是对象,但是返回结果都是数组,这就起到了将对象转成数组的目的。从上面代码可以看到,这个方法起作用的前提是,被处理的对象必须有length属性,以及相对应的数字键。
三、bind方法
bind方法用于将函数体内的this绑定到某个对象,然后返回一个新函数。格式如下:
func.bind(thisV, arg1, arg2,...)
bind比call方法和apply方法更进一步的是,除了绑定this以外,还可以绑定原函数的参数。
var add = function (x,y) { return x*this.m + y*this.n; } var obj = { m: 2, n: 2 }; var newAdd = add.bind(obj, 5); newAdd(5) // 20
上面代码中,bind方法除了绑定this对象,还绑定了add函数的第一个参数,结果newAdd函数只要一个参数就能运行了。
jquery中的$.proxy()方法和bind的作用基本相同
结合call方法使用:
利用bind方法,可以改写一些JavaScript原生方法的使用形式
var slice = Function.prototype.call.bind(Array.prototype.slice); slice([1, 2, 3], 0, 1) // [1]
通过bind将call绑定到Array.prototype.slice方法下,然后返回call给这个变量slice,
slice([],1,1)==Array.prototype.slice.call([],1,1)==>这个变量slice==Array.prototype.slice.call
可以这么理解先,哈哈我忽悠人了
var push = Function.prototype.call.bind(Array.prototype.push); var pop = Function.prototype.call.bind(Array.prototype.pop); var a = [1 ,2 ,3]; push(a, 4) a // [1, 2, 3, 4] pop(a) a // [1, 2, 3]
好啦,就扯这么多吧,这下应该是会用了~~

浙公网安备 33010602011771号