【问题标题】:call and apply in javascript [duplicate]在javascript中调用和应用[重复]
【发布时间】:2012-10-22 02:35:41
【问题描述】:

可能重复:
What’s the meaning to chain call and apply together?

我发现了一些这样的代码:

function fun() {
    return Function.prototype.call.apply(Array.prototype.slice, arguments);
}

我知道js中的callapply,但是当它们放在一起时我很困惑。

那我想知道

Function.prototype.call.apply(Array.prototype.slice, arguments)

等同于:

Array.prototype.slice.apply(arguments);

如果不是,第一行是做什么的?

【问题讨论】:

    标签: javascript


    【解决方案1】:

    好的,让我们通过替换来解决这个问题。我们开始:

    Function.prototype.call.apply(Array.prototype.slice, arguments);
    

    我们所知道的:

    1. Function.prototype.call 是一个函数。
    2. callthis 指针指向Function.prototype
    3. 我们使用applycallthis指针改为Array.prototype.slice
    4. arguments应用(不作为参数传递)到call

    因此上面的语句等价于:

    Array.prototype.slice.call(arguments[0], arguments[1], ...);
    

    由此我们看到:

    1. Array.prototype.slice 是一个函数。
    2. slicethis 指针指向Array.prototype
    3. 我们使用callslicethis指针改为arguments[0]
    4. arguments[1], ... 作为参数传递给slice

    这与:

    arguments[0].slice(arguments[1], ...);
    

    这样做的好处是我们在一行中为slice 创建了一个fast unbound wrapper

    编辑:创建快速未绑定包装器的更好方法如下(请注意,它可能不适用于某些较旧的浏览器,但您现在不必担心 - 您可以对于不支持bind的浏览器,请始终使用shim):

    var slice = Function.prototype.call.bind(Array.prototype.slice);
    

    这与:

    function slice() {
        return Function.prototype.call.apply(Array.prototype.slice, arguments);
    }
    

    它是如何工作的:

    1. Function.prototype.call 是一个函数。
    2. callthis 指针指向Function.prototype
    3. 我们使用bindcallthis指针改为Array.prototype.slice
    4. bind 返回一个函数,其 arguments应用call

    奖励:如果你的编程风格像我的一样功能强大,那么你会发现这段代码非常有用:

    var funct = Function.prototype;
    var obj = Object.prototype;
    var arr = Array.prototype;
    
    var bind = funct.bind;
    
    var unbind = bind.bind(bind);
    var call = unbind(funct.call);
    var apply = unbind(funct.apply);
    
    var classOf = call(obj.toString);
    var ownPropertyOf = call(obj.hasOwnProperty);
    var concatenate = call(arr.concat);
    var arrayFrom = call(arr.slice);
    
    1. 使用它,您可以使用callapply 轻松创建未绑定的包装器。
    2. 您可以使用classOf 来获取值的内部[[Class]]
    3. 您可以在 for in 循环中使用 ownPropertyOf
    4. 您可以使用concatenate 来加入数组。
    5. 您可以使用arrayFrom 创建数组。

    【讨论】:

    • Function.prototype.bind.call(Function.prototype.bind, Function.prototype.bind) :-)
    • @Bergi - 与Function.prototype.bind.bind(Function.prototype.bind) 相同。 =)
    • 是真的吗? Function.prototype.bind.bind(Function.prototype.bind) === Function.prototype.bind.bind 来自您的算法... @AaditMShah
    【解决方案2】:

    通过以下行,.apply 正在调用 .call 方法,其中 .call 的调用上下文是 .slice 方法,arguments 集合作为单独的参数传递。

    Function.prototype.call.apply(Array.prototype.slice, arguments);
    

    这实际上给了我们这个:

    Array.prototype.slice.call(arguments[0], arguments[1], arguments[2] /*, etc */);
    

    这意味着.slice() 将被调用,arguments 对象中的第一项作为调用上下文,其余参数作为普通参数。

    所以如果arguments 的内容是这样的:

    myarray, 0, 5
    

    你实际上是这样结束的:

    myarray.slice(0, 5)
    

    这基本上是一种不必这样做的方式:

    var arr = arguments[0];
    var rest = Array.prototype.slice(arguments, 1);
    
    var result = arr.slice.apply(arr, rest);
    

    【讨论】:

      猜你喜欢
      • 2011-05-24
      • 2012-12-30
      • 2012-09-07
      • 2014-03-11
      • 1970-01-01
      • 1970-01-01
      • 2010-11-22
      • 2013-08-17
      相关资源
      最近更新 更多