javascript的call、apply、bind

相同点

1,都是Function对象原型链的扩展方法,都可以改变把Function对象中的this的指向

不同点

1, call(thisObj[, arg1][, arg2]...)

var foo = {
    name : 'foo1',
    say : function (word1, word2) {
        console.log(this.name, word1, word2)
    }
}
var moo = {
    name : 'foo2'
}
foo.say.call(moo); // foo2 undefined undefined
foo.say.call(moo, 'hell', 'wu') // foo2, hell, wu

call把当前对象的this指向第一个参数,后面参数为可选分别为调用方法的参数

2,apply(thiobj[, [arg1[,arg2][,arg3]]]);

var foo = {
    name : 'foo1',
    say : function (word1, word2) {
        console.log(this.name, word1, word2)
    }
}
var moo = {
    name : 'foo2'
}
foo.say.apply(moo); // foo2 undefined undefined
foo.say.apply(moo, ['hell', 'wu']) // foo2, hell, wu

call与apply方法用法基本相同,除了传参形式。apply第二个参数为数组,分别魏颖调用发方法的参数。

此外,apply经常把类数组的对象,转成数组:

var foos = document.getElementByClassName('foo');
Array.prototype.slice.apply(foos); //foos 已变成数组

3, fun.bind(thisAry[, arg1[, arg2]]);

调用bind的方法会产生一个新函数,指向thisary。与apply和call的区别是bind产生的新方法,可以被变量引用保存到内存中,一直使用。

var foo = {
    name : 'foo1',
    say : function (word1, word2) {
        console.log(this.name, word1, word2)
    }
}
var moo = {
    name : 'foo2'
}
foo.say.bind(moo)() // foo2
foo.say.bind(moo)('hell', 'hah') // foo2, hell ,hah
var newfoo = foo.say.bind(moo)();
newfoo('hell', 'hah') // foo2 hell haha

当然,bind是ESCM5后的方法,所以IE8不支持:

if (!Function.prototype.bind) { //若浏览器不支持bind方法
    Function.prototype.bind = function (oThis) { //oThis 是bind所传参数,包括this指示对象以及绑定方法所需参数
        if (typeof this !== 'function') { //this指的是bind所绑定的方法,若不是函数则抛出错误
            throw new TypeError('绑定方法不是一个函数');
        }

        var aArgs = Arrayprototype.slice.call(arguments,1),
        //通过slice方法截取bind参数索引为1开始一直到最后的参数,即除了this后面参数。arguments 指 bind所传参数
        fTobind = this, //绑定的函数
        fNOP = function (){}, //空的函数,
        fBound = function () {
            return fToBind.apply(this instanceof fNOP && oThis ? this : oThis || window, aArgs.concat(Array.prototype.slice.call(arguments)));//this 是绑定的函数, fNOP作为空的函数,this instanceof fNOP会返回false,所以this instanceof fNOP && oThis ? this : oThis || window只会返回 oThis ,若oThis为空的时候,返回window。aArgs.concat(Array.prototype.slice.call(arguments)))返回 bind 绑定返回的方法运行时候所传的参数。 这样 整个fBound 返回oThis的第一个对象直接调用方法。
        }
        fNOp.prototype = this.prototype; //复制要绑定的函数到fNoP函数的原型链
        fBound.prototype = new fNOP(); 
        return fBound;
    }
}
Written on June 3, 2015