【问题标题】:How to pass an arguments array to a function without changing context?如何在不更改上下文的情况下将参数数组传递给函数?
【发布时间】:2015-05-11 08:39:59
【问题描述】:

我正在处理每个都绑定到特定上下文的函数。在代码的其他地方,我必须使用可变数量的参数来调用它们。通常情况下,我会使用 apply,但这会改变上下文 (this)。

我可以在不改变函数中this的现有绑定值的情况下实现apply( null, args )的效果吗?

(当需要调用时,我手头没有函数this 的值。)

顺便说一句,这里的问题不是 that one 的重复,尽管标题很有希望,OP 只是试图在方法调用中添加语法糖。

【问题讨论】:

  • 你能提供一些示例代码吗?
  • 举个例子就好了。如果问题的根源在于代码的体系结构,我想不出你称之为some.method.apply(null, args) 的地方你不能做到some.method.apply(some, args)
  • 不调用函数this必须在函数中窗口引用,我不确定你在这个内部函数中是否有不同的引用,即使你可以通过apply(window, args)方法
  • 使用apply( this, args )。你说你在变量中没有this,但你肯定在this 中有this,是吗?

标签: javascript


【解决方案1】:

令人惊讶的是,事实证明这不是问题。如果函数绑定到上下文,则可以使用apply 安全地调用它,而无需更改上下文。

apply 的第一个参数可以设置为任何值 - undefinednullwindow、另一个对象。如果函数被绑定,则没有任何作用。

例子:

var o = { id: "foo" },
    args = [ "bar", "baz" ],
    f = function () {
      var args = Array.prototype.slice.call( arguments ).join( ", ");
      return "Called in the context of " + this.id + " with args " + args; 
    },

    // Binding f to o with ES5 bind
    boundNative = f.bind( o ),

    // Binding f to o with a closure
    boundWithClosure = ( function ( context ) { 
        return function () { 
            return f.apply( context, arguments ); 
        } 
    } )( o );

// Does boundNative.apply( whatever, args ) change the context?
console.log( boundNative.apply( undefined, args ) );
console.log( boundNative.apply( null, args ) );
console.log( boundNative.apply( window, args ) );
console.log( boundNative.apply( { id: "quux" }, args ) );

// Same test with the closure
console.log( boundWithClosure.apply( undefined, args ) );
console.log( boundWithClosure.apply( null, args ) );
console.log( boundWithClosure.apply( window, args ) );
console.log( boundWithClosure.apply( { id: "quux" }, args ) );

所有调用都返回“在带有 args bar、baz 的 foo 上下文中调用”,所以没有问题。

我不得不承认,这个结果一开始让我很吃惊。毕竟,apply 强制执行上下文 - 为什么会被忽略?但实际上它完全有道理。

是的,原始函数(f)引用this,用apply调用它会改变它的值。但是我们没有调用原始函数。

绑定的函数是一个完全独立的实体,它不再引用this。对于 ES5 bind 来说,这不是很明显,但是闭包结构把它暴露了。 this 关键字不会出现在 IIFE 返回的函数中的任何位置。调用它,apply 没有什么可以改变的。

【讨论】:

    【解决方案2】:

    上下文总是存在的,它可以是全局对象(窗口)或某个特定对象的上下文。当你调用一个函数时,它会使用一些上下文。此外,您绝对应该可以访问它。函数存在于可见范围内(上下文和范围不一样)

    var text = "Current context is ";
    
    function A() {
        this.test = "A";
        this.print = function(msg) {
            return msg + this.test;
        }
    };
    
    function B() {
        this.test = "B";
    }
    
    var testObj = {
        test: "testObj"
    };
    
    test = "window";
    
    var msgFn = function (msg) {
        return msg + "msgFn";
    }
    
    var a = new A();
    var b = new B();
    
    a.print.apply(a, [text]); // Current context is A
    a.print.apply(b, [text]); // Current context is B
    a.print.apply(null, [text]); // Current context is window
    a.print.apply(testObj, [text]); // Current context is testObj
    msgFn.apply(msgFn, [text]); // // Current context is msgFn
    

    【讨论】:

      猜你喜欢
      • 2020-09-10
      • 1970-01-01
      • 2017-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-14
      • 2015-04-29
      相关资源
      最近更新 更多