JavaScript:call,apply,bind的用法

var jane = {
    name: 'Jane',
    sayHelloTo: function (otherName) {
        'use strict';
        console.log(this.name+' says hello to '+otherName);
    }
};

Function.prototype.call(thisValue, arg1?, arg2?, …)

第一个参数将被指向被调用函数的this值,其它的参数讲是调用函数所需要用到的。
下面三种调用所得到的结果是一样的

jane.sayHelloTo('Tarzan');

jane.sayHelloTo.call(jane, 'Tarzan');

var func = jane.sayHelloTo;
func.call(jane, 'Tarzan');

对于第二种方法,还需要把jane传入,因为call()并不知道你调用的是哪个对象。

Function.prototype.apply(thisValue, argArray)

其实,apply()与call()总体是一样的,只不apply()的第二个参数是以数组的形式传入。

jane.sayHelloTo('Tarzan');

jane.sayHelloTo.apply(jane, ['Tarzan']);

var func = jane.sayHelloTo;
func.apply(jane, ['Tarzan']);

Function.prototype.bind(thisValue, arg1?, …, argN?)

通过调用bind()方法,产生了一个新的函数,thisValue将赋值给新函数的this,参数从arg1到argN。

function func() {
    console.log('this: '+this);
    console.log('arguments: '+Array.prototype.slice.call(arguments));
}
var bound = func.bind('abc', 1, 2);

> bound(3)
this: abc
arguments: 1,2,3

下面三种方法调用产生的结果是一样的。

jane.sayHelloTo('Tarzan');

var func1 = jane.sayHelloTo.bind(jane);
func1('Tarzan');

var func2 = jane.sayHelloTo.bind(jane, 'Tarzan');
func2();

可以看出,call()和apply()调用之后,立即执行了, 调用bind()并没有立即执行,因为调用它产生了一个新的函数,得去调用这个新的函数,才能执行。

apply() for Constructors

现在有一个数组,选出数组中最大的值。

var array = [10,5,6,12];

当然,有很多方法可以实现。
现在通过Math.max()实现,下面的用法肯定很熟悉啦。

> Math.max(10,5,6,12)
  12

对于函数而言,我们可以通过apply达到上面的效果。

> Math.max.apply(null,array)
  12

apply仅仅在对函数或方法调用有作用

在构造器上调用apply()

这里以new Date()为例
第一步:
给Data传递参数

new (Date.bind(null,2015,9.17))

第二步:
因为bind()是一个方法,所以我们可以对它apply().使用apply()给bind()传递一个数组。

new (Function.prototype.bind.apply(
         Date, [null, 2011, 11, 24]))

稍作修改:

var arr = [2011, 11, 24];
new (Function.prototype.bind.apply(
         Date, [null].concat(arr)))

做个简单的封装:

if (!Function.prototype.construct) {
    Function.prototype.construct = function(argArray) {
        if (! Array.isArray(argArray)) {
            throw new TypeError("Argument must be an array");
        }
        var constr = this;
        var nullaryFunc = Function.prototype.bind.apply(
            constr, [null].concat(argArray));
        return new nullaryFunc();
    };
}

用法:

> Date.construct([2015,9,17])

Sat Oct 17 2015 00:00:00 GMT+0800 (中国标准时间)

抽离一个方法时this的指向

何谓抽离一个方法?就是将一个对象中的某个方法单独提取出来赋值给一个变量,这个变量又是一个函数了。
比如:

var counter = {
    count: 0,
    inc: function () {
        this.count++;
    }
}

将inc提取出来:

> var func = counter.inc;
> func() //undefined
> counter.inc  // didn’t work
0

这是为什么呢?
在执行counter.inc操作时,this已经指向了全局对象,相当于进行了window.count++操作。因为window.count不存在,那也就是undefined,对它进行++操作,得到的结果就是NaN了。

再严格模式下,它就会报错。

> counter.inc = function () { 'use strict'; this.count++ };
> var func2 = counter.inc;
> func2()
TypeError: Cannot read property 'count' of undefined

在严格模式下,this的值是undefined。

正确的抽离一个方法

那就是运用bind()了。

> var func3 = counter.inc.bind(counter);
> func3()
> counter.count  // it worked!
1

你可能感兴趣的:(javascript)