使用调用并在Javascript中应用的上下文?


74

伙计们可以解释使用Java的上下文callapply方法吗?

为什么使用callapply不是直接调用函数?


3
阅读的内容帮助我理解了thisArg致电时的重点apply()call()这似乎是您问题的核心。您需要了解Javascript中的函数调用原语
Saba Ahang

Answers:


80

您可以使用callapply当您要将不同的this值传递给函数时。从本质上讲,这意味着您希望像执行特定对象的方法一样执行函数。两者之间的唯一区别是call期望参数用逗号分隔,而apply期望参数在数组中。

Mozillaapply页面上的示例,其中构造函数被链接在一起:

function Product(name, price) {
    this.name = name;
    this.price = price;

    if (price < 0)
        throw RangeError('Cannot create product "' + name + '" with a negative price');
    return this;
}

function Food(name, price) {
    Product.apply(this, arguments);
    this.category = 'food';
}
Food.prototype = new Product();

function Toy(name, price) {
    Product.apply(this, arguments);
    this.category = 'toy';
}
Toy.prototype = new Product();

var cheese = new Food('feta', 5);
var fun = new Toy('robot', 40);

什么Product.apply(this, arguments)所做的是以下情况:该Product构造函数被施加为在每个的功能FoodToy构造,并且每个这些对象实例的正与传递this。因此,每一个FoodToy现在拥有this.namethis.category性能。


6
只是有关提供的代码段的问题,为什么玩具和食品的原型被Product对象代替?
大卫

评论只是为了解决@davids问题:为什么我们需要这样做Toy.prototype = new Product();?我对此进行了测试,删除这些行似乎对最终结果没有影响。
adrianp

6
@davids&@adrianp:需要使食品和玩具从Product继承。看下面的示例:jsfiddle.net/Shawn/xNEYf我删除了Toy.prototype = new Product();但留了下来Food.prototype = new Product();,所以Food继承了Product,而Toy却没有。我还在Product的原型中添加了一个方法,并从Food和Toy调用了该方法,以使继承的缺失更加明显(只需打开控制台并运行代码,Food可以调用从Product继承的方法,但是Toy不能并引发错误) 。
肖恩

与对象文字一起使用时,原型将如何使用?
user244394

我想我只是不了解执行此操作的目的,而是不了解似乎更简单的操作(例如this)

22

仅当您使用callapply可以this在函数内部修改上下文时。

与其他语言不同,JavaScriptthis中的不是引用当前对象,而是执行上下文,可以由调用者设置。

如果使用new关键字调用函数,this则将正确引用新对象(在构造函数内部)。

但在所有其他情况下-this除非通过调用明确设置,否则将引用全局对象


如果使用obj.whatever();语法,则它可能引用调用方obj 。
Abhishek Soni

语句“但是在所有其他情况下-除非通过调用显式设置,否则将引用全局对象”应更正为:“但是在所有其他情况下,除非通过调用进行显式设置,否则在使用时将引用全局对象在非严格模式下的Ecmascript 3或Ecmascript 5(或更高版本)。但是,在具有严格模式的Ecmascript 5(或更高版本)中,如果未明确设置,则始终是未定义的,并且当您访问它时,JS引擎将引发异常。” 参见:stackoverflow.com/questions/9822561/...
阿伦CS

10

您可以使用.call(),当你想引起不同的执行函数this值。它this按指定设置值,按指定设置参数,然后调用函数。.call()与执行函数之间的区别是执行函数this时指针的值。当您正常执行该函数时,javascript会决定this指针是什么(通常是全局上下文,window除非将该函数作为对象上的方法调用)。使用时.call(),您可以精确指定要this设置的内容。

您可以使用.apply(),当你想传递给函数的参数是一个数组。 .apply()也会导致函数以特定this值执行。 .apply()当您不确定地来自其他来源的参数数量时,最常使用该参数。它也经常通过使用特殊的局部变量来将参数从一个函数调用传递到另一个函数,该局部变量arguments包含传递给当前函数的参数数组。

我找到了MDN引用页面.CALL()。适用()有帮助。


谢谢,您解释得很好。最终了解第一个参数的用法。
问题溢出

4

如果您有使用jQuery的经验,您将知道大多数函数都使用该this对象。例如,collection.each(function() { ... }); 在此函数内部,"this"引用迭代器对象。这是一种可能的用法。

我个人曾经用于.apply()实现请求队列-我将参数数组推入队列,当需要执行该参数时,我采用一个元素,并将其作为处理程序函数的参数传递给.apply(),从而使如果必须将参数数组作为第一个参数传递,则使用代码清理器。那是另一个例子。

通常,请记住,存在那些调用函数的方法,您可能有一天会发现它们可方便地用于实现程序。


1

如果您有经验,Object Oriented Programming那么将继承与继承进行比较,并从子类覆盖父类的属性或方法/函数,则调用并应用将很有意义。与javascript中的调用类似,如下所示:

function foo () {
  this.helloworld = "hello from foo"
}
foo.prototype.print = function () {
  console.log(this.helloworld)
}

foo.prototype.main = function () {
  this.print()
}


function bar() {
  this.helloworld = 'hello from bar'
}
// declaring print function to override the previous print
bar.prototype.print = function () {
  console.log(this.helloworld)
}

var iamfoo = new foo()

iamfoo.main() // prints: hello from foo

iamfoo.main.call(new bar()) // override print and prints: hello from bar

0

我想不出任何正常情况,将thisArg设置为不同的东西是使用apply的目的。

apply的目的是将值数组传递给希望将这些值作为参数的函数。

它已被点播运营商取代为所有常规日常使用。

例如

// Finding the largest number in an array
`Math.max.apply(null, arr)` becomes `Math.max(...arr)`

// Inserting the values of one array at the start of another
Array.prototype.unshift.apply(arr1, arr2); 
// which becomes 
arr1 = [...arr2, ...arr1]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.