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]

好啦,就扯这么多吧,这下应该是会用了~~

 

posted @ 2016-06-01 16:46  暗夜心慌方  阅读(298)  评论(0)    收藏  举报