这个 apply() 在 JavaScript 中是什么意思?

9

请问,下面代码中的this.init.apply(this, arguments)是什么意思?

我知道apply()的一般意义,但是在下面代码的上下文中,它的作用是什么?

var Class = function() {

    var klass = function() {
        this.init.apply(this, arguments); //I don't really get this bit...
    };

    klass.prototype.init = function(){};

    return klass;
};

var Person = new Class;

//Usage
var someone =  new Person;

我看到很多人在使用它。我有一个大概的想法,但无法真正掌握它,所以我需要更多的信息。

我正在提高我的JS水平,所以我想了解关于它的一切,而不仅仅是简单的“Hello world”级别。

非常感谢。


5
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply - SLaks
4
您在谷歌搜索该方法时是否有不太清晰的地方?(原意:该方法的描述是否有不清楚的地方?) - Jeff
2
谢谢@Jeff。是的,我不明白为什么上面的代码中init被定义了两次。我提出的问题是关于apply()应用的上下文。 - Shaoz
1个回答

9

apply 是一个函数对象的成员函数。假设我们有:

function saySomething(thing, anotherThing) {
    alert(this + " says " + thing + " and " + anotherThing);
}

然后我们可以使用以下代码:
saySomething.apply(document, ["hello", "goodbye"]);

这个调用函数,将数组的值作为参数传递给函数。第一个参数指定函数的上下文(或者说在函数运行时,this 等于什么)。
你应该也知道 arguments 是一个特殊的变量,它包含了传递给函数的所有参数的数组。因此,在这里,this.init.apply(this, arguments) 的意思是调用 init 函数,并将传递给 klass 构造函数的所有参数都传递给它。
在实际实现中,我认为 init 会期望有参数。考虑一下如果没有使用 apply,应该如何完成:
var klass = function(arg1, arg2, arg3) {
    init(arg1, arg2, arg3);
}

klass.prototype.init = function(arg1, arg2, arg3) {}

如果您想要将arg4添加到init中,您需要在三个地方添加它!通过使klass将其所有参数透明地传递给init,可以使您的代码更加健壮。

非常感谢@apsillers。但是为什么它在自身内部调用init()?为什么不直接使用klass.prototype.init()?对于这个问题打扰你了,我喜欢事情清晰明了... - Shaoz
2
它旨在使klass完全透明 - 尽管在构建新实例时调用了klass,但init函数才是真正进行“重活”的函数,并且它可能需要参数。 为了避免在klassinit上重复参数列表的麻烦,klass不带命名参数,仅通过使用applyarguments将所有参数传递给init。 为什么要这样做?我对Klass库的了解还不够,无法说出原因。 - apsillers
已编辑以进一步澄清。 - apsillers
现在我明白了,非常感谢。这就是我想要澄清事情的解释...但是,除了这种技术之外,是否可以使用对象作为参数?例如,将键/值属性作为参数...即{key1: value1, key2: value2,...keyN: valueN}... - Shaoz
当然,这是一个完全有效且不常见的模式,您可以使用它来代替(或与)apply/arguments模式一起使用。 - apsillers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接