2011-12-28 49 views
60

伙计们可以解释上下文在Javascript中使用callapply方法吗?上下文使用调用并在Javascript中应用?

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

+2

[该读(https://t.co/BVQPwfqqnO)帮助调用'适用()时,我明白thisArg'的'点'和'通话()'这似乎是你问题的核心。您需要了解Javascript中的函数调用原语 – 2015-10-26 20:54:35

回答

20

仅当您使用callapply时,您才可以修改函数内的this上下文。

与其他语言不同 - 在JavaScript中this不引用当前对象 - 而是引用执行上下文并可由调用者设置。

如果你调用一个函数使用new关键字this将正确引用新的对象(构造函数中)..

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

+0

如果使用'obj.whatever();'语法,它可能会引用调用者obj。 – 2016-06-17 14:13:52

+0

声明“但在所有其他情况下 - 这将引用全局对象,除非通过调用明确设置”应该更正为:“但在其他所有情况下,除非通过调用明确设置,否则这将引用全局对象if在非严格模式下使用Ecmascript 3或Ecmascript 5(或更高版本),但在具有严格模式的Ecmascript 5(或更高版本)中,如果未明确设置,则始终未定义,并且JS引擎在您访问时会引发异常。请参阅:http://stackoverflow.com/questions/9822561/why-is-this-in-an-anonymous-function-undefined-when-using-strict – 2016-06-21 19:49:03

68

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

Mozilla's apply page,其中构造被链接的一个例子:

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属性。

+5

只是一个关于提供的代码片段的问题,为什么玩具和食品的原型被Product对象替换? – davids 2012-10-19 09:56:30

+0

评论仅仅是碰到@davids问题:为什么我们需要做'Toy.prototype = new Product();'?我测试了这一点,删除这些行看起来没有什么区别,最终的结果。 – adrianp 2013-05-13 13:49:29

+6

@davids&@adrianp:制作食品和玩具需要继承产品。看看这个例子:http://jsfiddle.net/Shawn/xNEYf/我删除了'Toy.prototype = new Product();'但是离开了'Food.prototype = new Product();'in,所以现在Food继承自产品,但玩具不。我还在Product的原型中添加了一个方法,并从Food and Toy中调用它以使缺乏继承更加明显(只需打开控制台并运行代码,Food可以调用从Product继承的方法,但Toy不能并引发错误) 。 – Shawn 2013-07-17 19:55:00

3

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

我个人已经使用.apply()来实现一个请求队列 - 我将一个参数数组插入到队列中,当执行它的时候,我接收一个元素并将其作为处理函数的参数传递使用.apply(),因此如果必须传递一个参数数组作为第一个参数,那么代码更清晰。这是另一个例子。

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

6

如果要使函数以不同的this值执行,则使用.call()。它根据指定设置this值,根据指定设置参数,然后调用函数。 .call()与仅执行该函数的区别在于函数执行时this指针的值。当你正常执行这个函数时,javascript会决定指针的位置(通常是全局上下文window,除非函数被调用为对象的方法)。当您使用.call()时,您可以确切指定要将this设置为的内容。

如果要传递给函数的参数在数组中,则使用.apply().apply()也可以导致函数执行一个特定的this值。 .apply()最常用于来自其他来源的不确定数量的参数。它通常也用于通过使用特殊的局部变量arguments将参数从一个函数调用传递到另一个函数调用,其中包含传递给当前函数的参数数组。

我觉得.call().apply()的MDN参考页有帮助。

+0

谢谢,你解释得很好。最后了解第一个参数的用法。 – 2012-07-21 13:50:22

0

我想不出任何将thisArg设置为不同的正常情况是使用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] 
0

如果你有经验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 
相关问题