我一直在阅读一堆谈论JavaScript面试问题的网页,我注意到很多人都说知道.call()和.apply之间的区别很重要。 ()。
例如:
http://www.sitepoint.com/5-typical-javascript-interview-exercises/
https://github.com/h5bp/Front-end-Developer-Interview-Questions
对于我的生活,我无法理解为什么这被认为是如此重要。有人知道吗?对我而言,它可能与了解js长日期和js短日期之间的区别同样重要(也就是说,它对我来说似乎并不重要)。我的直觉告诉我某个有影响力的人说,知道.call()和.apply()之间的区别是至关重要的,每个人都只是复制了这个人说的话。但也许我误解了.call()和.apply()的一些事情?我不确定。
答案 0 :(得分:5)
简单地说,更高级的Javascript类型偶尔需要使用.call()
或.apply()
,特别是试图代理函数并传递参数或控制{{1}的值的代码}。
如果您正在做这些类型的事情,那么您必须知道this
和.call()
的工作方式,以便您可以使用正确的方法(因为他们不工作相同)。如果你没有做那些类型的高级内容,那么很多Javascript都可以在不使用它们的情况下编写。
作为一个面试问题,我认为这是一个合理的考验,你是否理解了参数传递,调用方法和Javascript中.apply()
处理的一些更高级的细微差别。如果你想在这些类型的问题上做得好,你需要同时理解this
和.call()
,现在如何解释他们做了什么以及如何以及何时使用它们以及何时使用与另一个。
.apply()
的整个概念及其在Javascript中的控制或设置方式往往不被经验较少的Javascript程序员所理解(哎呀我甚至看到一些经验丰富的开发人员并不理解好吧)所以对与之相关的事情进行问答是一个合理的测试,this
和.call()
对此有点重要。
如果您正在开发库或框架代码,那么您在工作中更有可能使用.apply()
或.call()
。
这是一个基本摘要:
Javascript中的每个函数都是一个具有一些属性的对象。因此,除了能够调用.apply()
之类的函数之外,您还可以像func()
一样引用它上面的属性。
每个函数的两个属性是func.length
和.call()
。它们都允许您以不同的方式调用函数,而不是仅将其称为.apply()
。
<强> .CALL()强>
当然,我们都知道,如果你只想调用一个具有固定数量参数的函数,你可以只执行func()
并将这些参数传递给函数,但是如果你想要控制传递这些固定参数时func(arg1, arg2)
值是什么?将func调用为this
将导致该函数内的func(arg1, arg2)
值设置为浏览器中this
的全局对象或者以严格模式运行window
}。 Javascript中的每个函数调用(例如undefined
)都以这种方式重置func(arg1, arg2)
指针。这是this
的用武之地。您可以执行:
.call()
它会与func.call(someThisValue, arg1, arg2)
做同样的事情,除非它会导致func(arg1, arg2)
指针设置为this
。
注意:您也可以只使用一个参数使用someThisValue
,它只会设置.call()
指针而不传递任何参数。
this
<强>。适用()强>
但是,如果您的参数列表没有修复并且您的参数位于可变长度数组或类似数组的对象中,该怎么办?您无法真正使用func.call(someThisValue)
,因为您无法为每个可能的参数列表键入正确的.call()
语句。这就是.call()
的用武之地。.apply()
的规范用法是当您尝试从其他函数调用传递参数时。当你代理其他函数调用稍微修改它们的行为时,这是很常见的,但仍然会调用原始函数,而原始函数也有各种形式(因此你不能完全知道传递的参数)或许多不同类型的函数调用都通过这个代理。在这种情况下,您可以使用.apply()
,通常使用.apply()
对象。您可以在MDN polyfill for .bind()
中找到相关示例。
假设我想挂钩一些名为arguments
的现有函数用于记录,doIt()
有许多不同的方法可以调用它。使用doIt()
,我可以这样做:
.apply()
仅供参考,// regular function already defined in your program
function doIt(arg1, arg2) {
// do something
}
// then actual usage elsewhere in the program would be just this:
doIt("foo", "bar");
// now install a proxy that can intercept all calls to doIt() and
// add some behavior before and after
(function(origDoIt) {
// replace doIt function with my own proxy
doIt = function() {
console.log("before doIt()");
// call the original function with all the arguments and this pointer
// that were passed
var retVal = origDoIt.apply(this, arguments);
console.log("after doIt()");
return retVal;
}
})(doIt);
也可用于将.apply()
指针设置为:
this
在该特定情况下(仅限于该情况),它与func.apply(someThisValue)
完全相同。
这是我最喜欢的.call()
用途之一。 .apply()
方法接受可变数量的参数,它将返回任何这些参数的最大数量。因此:
Math.max()
将返回Math.max(1,2,3,4)
。
但是,使用4
,我们可以在任何数组中找到最大数字。
.apply()
我们正在使用var list = [999,888,777,666,555,444,333,1000];
var m = Math.max.apply(Math, list);
console.log(m); // 1000
将整个.apply()
数组作为list
的参数发送,因此它将对整个数组进行操作。
注意,当ES6在任何地方或在您的特定执行环境中完全实现时,您也可以使用新的扩展运算符来执行类似的操作:
Math.max()
这成为我们使用var list = [999,888,777,666,555,444,333,1000];
var m = Math.max(...list);
console.log(m); // 1000