连锁调用和一起应用是什么意思

What's the meaning to chain call and apply together?

本文关键字:应用 是什么 意思 一起 调用      更新时间:2024-03-17

我在jsGarden中遇到了这段代码,我无法弄清楚将callapply链接在一起的含义。两者都将使用给定的上下文对象执行函数,为什么它可以链接?

function Foo() {}
Foo.prototype.method = function(a, b, c) {
    console.log(this, a, b, c);
};
// Create an unbound version of "method" 
// It takes the parameters: this, arg1, arg2...argN
Foo.method = function() {
    // Result: Foo.prototype.method.call(this, arg1, arg2... argN)
    Function.call.apply(Foo.prototype.method, arguments);
};

它通过apply调用call;也就是说,它使用call来调用函数("方法"(,并且它使用apply进行调用,因为它以(几乎(数组的形式获得参数。

所以拆开它:

Function.call

这是对所有函数实例上可用的call()函数的引用,继承自函数原型。

Function.call.apply

这是通过对call函数的引用,对apply的引用。 由于apply是通过 call 对象引用的,因此在调用 apply 时,this值将是对 call 函数的引用。

Function.call.apply(Foo.prototype.method, arguments);

所以我们通过 apply 调用 call 函数,并将Foo.prototype.method传递给this值,并将参数传递给"Foo.mmethod"作为参数。

我认为它与以下效果基本相同:

Foo.method = function() {
  var obj = arguments[0], args = [].slice.call(arguments, 1);
  Foo.prototype.method.apply(obj, args);
}

但我必须尝试一下以确保。编辑是的,似乎就是这样。 因此,我可以将该技巧的重点总结为当所需的this值是保存参数的数组的第一个元素时调用apply()的一种方式。 换句话说,通常当你调用apply()时,你已经得到了所需的this对象引用,并且你已经得到了参数(在数组中(。 但是,在这里,由于这个想法是将所需的this作为参数传递,因此需要将其分离出来才能调用apply。 就个人而言,我会像我的"翻译"一样这样做,因为它(对我来说(不那么令人费解,但我想人们可以习惯它。根据我的经验,这不是常见的情况。

我认为代码应该是这样的:

function Foo() {}
Foo.prototype.method = function(a, b, c) {
 console.log(this, a, b, c);
};
Foo.method = function() {
 //Notice this line:
 Function.apply.call(Foo.prototype.method, this, arguments);
};

然后

Foo.method(1,2,3) => function Foo() {} 1 2 3

其他例子:

Function.apply.call(Array,this,[1,2]) => [1, 2]
Function.call.apply(Array,this,[1,2]) => [window]
Function.call.call(Array,this,[1,2])  => [[1, 2]]

apply确实将数组作为第二个参数,call采用单个参数。

 // lets take call,
 var callfn = Function.prototype.call;
 // an ordinary function from elsewhere
 var method = Foo.prototype.method;
 // and apply the arguments object on it:
 callfn.apply(method, arguments);

因此,第一个arguments项将是methodthis值,随后将填充单个参数。

结果是在Foo构造函数上method静态函数,该函数将Foo实例(或类似的东西(作为第一个参数,并在其上应用原型method。一个可能的用例是定义一个Object.hasOwnProperty函数,该函数通常仅作为Object.prototype.hasOwnProperty提供。

最终,如果您需要将method应用于a(不继承它或b(覆盖它的对象,它可以缩短一个"原型"和一个"调用"的调用。

Person.prototype.fullname = function(joiner, options) {
  options = options || { order: "western" };
  var first = options.order === "western" ? this.first : this.last;
  var last =  options.order === "western" ? this.last  : this.first;
  return first + (joiner || " ") + last;
};
// Create an unbound version of "fullname", usable on any object with 'first'
// and 'last' properties passed as the first argument. This wrapper will
// not need to change if fullname changes in number or order of arguments.
Person.fullname = function() {
  // Result: Person.prototype.fullname.call(this, joiner, ..., argN);
  return Function.call.apply(Person.prototype.fullname, arguments);
};

来自 Javascript Garden 的代码。

请注意,它声明了

Function.call.apply(Person.prototype.fullname, arguments(;
将变成这样:
Person.prototype.fullname.call(this, joiner, ..., argN(;

这意味着 apply(( 函数将首先被挖掘出来,然后调用(( 函数将被执行。

模式:最右边最call() / apply()将首先被执行

  1. 所以对了,大多数apply()将首先被执行
  2. apply()的上下文成为call()函数的调用方,所以现在
    Person.prototype,fullname.call((
  3. apply()只能接受一个参数数组,因此apply() call()函数提供了arguments,所以现在
    Person.prototype,fullname.call(arguments(

@foxiris的例子

第一条:

Function.apply.call(Array,this,[1,2](
  1. 最右边的call()将首先得到执行
  2. call()的上下文成为apply()的调用者,所以现在Array.apply()
  3. call()可以接受多个apply(),所以它可以提供this[1, 2],所以现在Array.apply(this, [1, 2]);,这将输出[1, 2]

第二个:

Function.call.apply(Array,this,[1,2](
  1. 最右apply()将首先得到执行
  2. apply()的上下文成为call()的调用者,所以现在Array.call()
  3. apply()只能接受一个数组参数,所以只能给call()提供this,所以现在Array.call(this);,输出是[]

第三一:

Function.call.call(Array,this,[1,2](
  1. 最右call()将首先得到执行
  2. call()的上下文(最右边的一个(成为call()的调用方(右边第二个(,所以现在Array.call()
  3. call()可以接受多个参数,因此它可以向另一个call()提供this[1, 2],所以现在Array.call(this, [1, 2]);,输出是[[1, 2]]