比较call( ) apply( ) bind( )

简朴比较一下call() apply() bind()

《JavaScript: The Definitive Guide》

call()与apply()

call()和apply()的第一个实参是要挪用函数的母对象,它是挪用上下文,在函数体内经由过程this来取得对它的援用。简朴来讲就是把一个要领绑定到一个对象上去挪用:

栗如,要想以对象o的要领来挪用函数f():

f.call(o);
f.apply(o);

实在相当于:

o.m = f; //将f存储为o的暂时要领
o.m(); //挪用它,不传入参数
delete o.m; //将暂时要领删除

–> 关于call(),第一个实参以后的一切实参就是要传入待挪用函数的值。栗如:

//以对象o的要领的情势挪用函数f(),并传入两个参数
f.call(o, 1, 2);

–> 关于apply(),它的实参都放入一个数组当中:

f.apply(o,[1, 2]);

给apply()传入的参数数组可所以恣意长度的,栗如:

//找出一个数组中最大的数值元素
var biggest = Math.max.apply(Math, array_of_numbers);

传入apply()的参数数组可所以类数组对象也可所以实在数组。实际上,能够将当前函数的arguments数组直接传入apply()来挪用另一个函数:

//将对象o中名为m的要领替换为另一个要领
//能够在挪用原始要领之前和以后纪录日记音讯
function trace(o, m) {
    var original = o[m];//在闭包中保留原始要领
    o[m] = function() {//定义新的要领
        console.log(new Date(), 'Entering', m);
        var result = original.apply(this, arguments);//挪用原始函数
        console.log(new Date(), 'Exiting', m);
        return result;
     };
}
//这个新要领是包裹原始要领的另一个泛函数 (monkey-patching)?

bind() 要领

bind()是ES5中的要领。
当在函数f()上挪用bind()要领并传入一个对象o作为参数,这个要领将返回一个新的函数,(以函数挪用的体式格局)挪用新的函数将会把原始的函数f()看成o的要领来挪用。传入新的函数的任何实参都讲传入原始函数。栗如:

function f(y) { return this.x + y; }
var o =  { x: 1 };
var g = f.bind(o);
g(2); //=> 3

能够用ES3简朴模仿:

function bind(f, o) {
    if(f.bind) return f.bind(o);
    else return function() {
        return f.apply(o, arguments);
    }
}

然则,bind()要领不仅仅是将函数绑定至一个对象—-除了第一个参数外,传入bind()的实参也会绑定至this,这个附带的应用是一种罕见的函数式编程技术,也被称为“柯里化“。

function f(y, z) { return this.x + y + z }
var g = f.bind({ x: 1 }, 2);
g(3);//=> 6 this.x绑定到1, y绑定到2, z绑定到3

假如用ES3模仿:

if(!Function.prototype.bind){
    Function.prototype.bind = function(o /*, args*/){
        //将this和arguments的值保留至变量中
        //以便在背面嵌套的函数中能够运用它们
        var self = this, boundArgs = arguments;
        
        //bind要领的返回值是一个函数
        return function(){
            //建立一个实参列表,将传入bind()的第二个及后续的实参传入这个参数
            var args = [], i;
            for(i=1; i<boundArgs.length; i++){
                args.push(boundArgs[i];
            }
            for(i=0;i<arguments.length;i++){
                args.push(arguments[i];
            }
            //如今将self作为o的要领来挪用,传入这些实参
            return self.apply(o, args);
        };
    };
}

http://web.jobbole.com/83642/
深入浅出妙用 Javascript 中 apply、call、bind

一个比较

var obj = {
    x: 81,
};
 
var foo = {
    getX: function() {
        return this.x;
    }
}
 
console.log(foo.getX.bind(obj)());  //81
console.log(foo.getX.call(obj));    //81
console.log(foo.getX.apply(obj));   //81

三个输出的都是81,然则注重看运用 bind() 要领的,他背面多了对括号。

也就是说,区别是,当你愿望转变上下文环境以后并不是马上实行,而是回调实行的时刻,运用 bind() 要领。而 apply/call 则会马上实行函数。

一个总结

  • apply 、 call 、bind 三者都是用来转变函数的this对象的指向的;

  • apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;

  • apply 、 call 、bind 三者都能够应用后续参数传参;

  • bind 是返回对应函数,便于稍后挪用;apply 、call 则是马上挪用 。

一道题:

定义一个 log 要领,让它能够代办 console.log 要领

function log(){
    console.log.apply(console, arguments);
}

若要给每个 log 音讯增加一个”(app)”的前辍?

//该怎么做比较文雅呢?这个时刻须要想到arguments参数是个伪数组,经由过程 //Array.prototype.slice.call 转化为规范数组,再运用数组要领unshift
function log(){
    var args = Array.prototype.slice.call(arguments);
    args.unshift('(app)');
    console.log.apply(console, args);
}
    原文作者:t1ree
    原文地址: https://segmentfault.com/a/1190000008812218
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞