【问题标题】:Why use this obj.method.call(obj, arg) and not obj.method(arg)?为什么使用这个 obj.method.call(obj, arg) 而不是 obj.method(arg)?
【发布时间】:2015-06-15 05:41:47
【问题描述】:

我有时会看到这种模式...

obj.method.call(obj, arg)  

我不明白为什么它不同于...

obj.method(arg)  

为什么要使用第一种模式?

天哪,似乎引起了很多讨论:)

为了澄清,我只是询问当方法所在的对象与call() 的第一个参数相同的情况(或者@FelixKling 说得更好:当 owner em> 与 receiver 相同)。我不是在问obj.method.call(obj2, arg)


如下所述,即使函数绑定的情况也无法区分这两种方法。

o2={p2:3};
o={p1:(function(){return this.p2}).bind(o2), p2:2};
o.p1() === o.p1.call(o) // true  

编辑

我猜这个成语的来源是用于重新绑定对象方法的模式......

obj.method.apply(obj, arguments)

【问题讨论】:

  • 没有什么不同。也许作者不知道更好。
  • 当然是不同的——从概念上讲。问题一般是关于 fn.call(scope, ...) 与 scope.fn(...) 的。即使提问者提出了相同的例子,他显然在这里问的是更微妙的东西。
  • @alecmc:我想我们只需要等到 OP 澄清这一点。就像你这样“清楚”地看到它,我“清楚地”看到它的另一种方式。
  • @alecmce 范围肯定不是问题吗?范围是关于声明上下文的,它是一样的吗? call() 是操纵 invocation context 我的问题是关于那个。

标签: javascript


【解决方案1】:

您发布的示例没有区别。但是,obj1.method.call(obj2, arg) 允许您在方法内部更改 thisobj.method.apply(obj, args) 让您拥有可变的参数计数。

例如,[].slice.call(arguments)(及其上级 Array.prototype.slice.call(arguments))是一个常见的习惯用法,它从非数组 (arguments) 接收器上的数组调用 slice

【讨论】:

  • 你为什么不做obj[methodname](arg)
  • @FelixKling:因为我是个白痴。 :D 是的,好点。将编辑。
  • 我比较确定 OP 知道 .call.apply 的优点,并且只询问特定用例,其中“所有者”与接收者相同。
  • @zerkms:实际上,是的,如果有人做傻事,他们可能会做不同的事情:var foo = function() { console.log("foo"); }; foo.call = function() { console.log("bar"); } 将导致foo() 打印“foo”,但foo.call(foo) 打印“bar”。
  • 赞成正确答案。这很奇怪,我也添加了正确的答案(甚至是第一个),但我有 2 票否决,天哪,为什么 :)
【解决方案2】:

为什么使用obj.method.call(obj, arg) 而不是obj.method(arg)

没有实际理由这样做。

在这两种情况下this 将引用obj,假设函数没有绑定到不同的值(在这种情况下,this 将始终是绑定值)。

【讨论】:

  • 这个模式有我想知道的名字吗?如果你用谷歌搜索,你会怎么称呼它?
  • 我认为没有这个名字。
  • 是的...o={p1:(function(){return this.p2}).bind(o2), p2:2}; o2={p2:3}; o.p1() === o.p1.call(o) // true 所以仍然没有区别。
  • 嗯,可惜不能在google上做正则表达式搜索
【解决方案3】:

如果方法中的第一个模式this 变量将指向obj 变量:

obj.method.call(obj, arg)

变量this 在第二种情况下将指向父变量,主要是window 变量。 您可以在控制台中检查是否执行以下操作:

var
  num = 1,
  pass = "Test",
  myFunc = function(expArg) {
    console.log(expArg);
    console.log(this);
  };

myFunc(pass);
// You would get "Test" and reference of window variable
myFunc.call(num, pass);
// You would get "Test" and number object with value of 1.

【讨论】:

  • 如果是第二个?
  • "变量 this 在第二种情况下将指向父变量,主要是一个窗口变量。" --- 你确定吗?
  • 您的示例与 OP 的示例不匹配。他们在谈论“方法调用”,而不是“函数调用”。鉴于,obj.method(arg)this 将始终引用 obj,除非它绑定到不同的值。
  • 重点是在第二个例子中,this 也将引用obj。这个问题与.call 无关。这是关于提供的两个示例之间的差异。你让它听起来好像没有区别。
  • 您所说的(部分)正确,但并非每个正确的陈述都能回答问题。 “天是蓝的”也是正确的说法,但没有回答这个问题。我说部分是因为 "Variable this 在第二种情况下会指向父变量," 是不正确的。在第二种情况下,this 引用obj,就像第一种情况一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-17
  • 1970-01-01
  • 2012-02-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-16
  • 1970-01-01
相关资源
最近更新 更多