.apply(Math, arrayName)在JS中是如何工作的?
How does .apply(Math, arrayName) work in JS?
关于如何在javascript中找到值数组的最小值或最大值,有多个stackoverflow问题。这不是那个问题。
我想知道为什么传递.apply()
奇怪的东西作为this
参数仍然有效。尽管Aaron Crane写了一篇关于Math对象的API是如何变成现在这个样子的博文,但仍有一些问题没有得到解答。
下面的每个代码片段都可以工作。我的问题是,怎么做?到底发生了什么分配给this
,使这些工作?
标准结构
var values = [45, 46, 47]
var min = Math.min.apply(Math, values);
alert(min); //45
一个更奇怪的结构,但范围可能很棘手…
var values = [45, 46, 47]
var min = Math.min.apply(this, values);
alert(min); //45
有点怪异
var values = [45, 46, 47]
var min = Math.min.apply(global, values);
alert(min); //45
更奇怪,但可能还好b/c浏览器
var values = [45, 46, 47]
var min = Math.min.apply(window, values);
alert(min); //45
非常奇怪
var values = [45, 46, 47]
var min = Math.min.apply(null, values);
alert(min); //45
真正奇怪的
var values = [45, 46, 47]
var min = Math.min.apply(undefined, values);
alert(min); //45
当使用.apply()
时,第一个参数控制当函数执行时this
指针的值将被设置为什么。在许多情况下,this
值非常重要。在少数情况下,this
值根本不在函数实现中使用(通常称为不操作实例数据的静态函数)。当不使用this
时,this
设置为什么无关紧要,因此.apply()
的第一个参数设置为什么无关紧要。
因此,在您的特定情况下,Math.min()
和Math.max()
(可能所有Math.xxx()
函数)根本不使用this
指针,因为它们基本上都是不操作实例数据的静态函数。所以,不管它被设置成什么,你可以把任何你想要的东西作为第一个参数传递给Math.min.apply()
,它不会改变函数调用的结果。
我认为仍然应该在那里传递正确的值,即Math
,因为当您执行正常操作时,this
将是这样的:
Math.min(x, y);
因此,要在使用.apply()
时向Math.min()
呈现与上述代码完全相同的情况,您可以这样做:
var arr = [x, y];
Math.min.apply(Math, arr);
在我看来,这促进了正确的习惯和正确的思考第一个参数应该是什么,因为它在其他情况下会很重要。
仅供参考,在jQuery中$.when.apply($, arr)
也经常出现类似的问题,在其实现中也不使用this
参数,因此可以将其称为$.when.apply(null, arr)
甚至$.when.apply("foo", arr)
。就我个人而言,我更喜欢通过"技术正确"考试。参数
仅供参考,在现代Javascript (ES2015+)中,对于这种特定类型的操作,您可以使用扩展语法来代替.apply()
:
const arr = [1,2];
const maxVal = Math.max(...arr);
并且,通过扩展语法自动将数组解压缩为单独的参数。并且没有决定传递什么给.apply()
的第一个参数,因为您只是进行完全相同的Math.max()
函数调用,没有任何操作。
TL;DR - Math.min()
和Math.max()
实际上并不使用传递给它们的this
参数,这只是让它们接受参数数组的一个hack,因为本机API只指定了一个变量列表。.apply()
可以接受参数数组,这就是使用它的原因。
我猜Math
是作为this
参数传入的,只是为了简洁。
感谢@Jonathan Lonowski和@Niet the Dark Absol。
apply
对它的第一个参数所做的只是为调用它的函数设置上下文(this
)。
比如说,你有一个这样的对象:
var obj = {
a: 1,
b: function () {
return this.a;
},
c: function () {
return 3;
}
}
如果你调用obj.b()
,你将得到1
作为返回值,因为this
在这个场景中是通过调用b
来定义的,obj
在它前面(this === obj
)。要更改它,您可以使用apply
:
obj.b.apply({a:2});
这将返回2,因为您现在显式地将this
设置为{a:2}
。
BUT:如果你有一个函数,没有内部使用this
,那么this
的值是什么并不重要。所以你可以调用:
obj.c();
或下列之一:
obj.apply.c(null);
obj.apply.c(undefined);
obj.apply.c("xyz");
但是你总是会得到相同的结果3
。这就像设置了一个永远不会用到的变量。不管它的价值是多少,都不会影响结果。
所以显然Math.min
不使用this
,因此在传递"无效"上下文时不会中断。
这(可以这么说)是JavaScript的一个棘手的部分。
当你有一个函数时,有一个神奇的变量叫做this
。根据调用函数的方式不同,它的上下文设置也不同。
function myFunction() {
return this;
}
var myObject = {
fn: function() {
return this;
}
};
myFunction(); // the global object. `window` in browsers, `global` in Node.js
myFunction.apply(Math); // Math
myFunction.apply({ hello: "world" }); // { hello: "world" }
myObject.fn(); // myObject
myObject.fn.apply(myObject); // myObject
myObject.fn.apply(Math); // Math
你上面的例子之所以有效是因为min
根本不使用this
,所以你可以把它分配给任何你想要的。
- Javascript:selenium Web驱动程序isDisplayed()不工作
- jQuery UI自动完成突然停止工作
- AngularJS UI路由器不能像ng路由器那样工作
- HTML5音频加载和播放获胜'我不能在iPad上工作
- JavaScript打印功能使日历停止工作
- Javascript.getHours()工作不正常
- 为什么这在IE中的工作方式与在Firefox中不同
- 视频HTML没有'无法在Internet Explorer 11上工作
- 扩展移相器按钮类不工作
- Firebase迁移-简单的Firebase.set没有'不再工作了——旧的还是新的
- 谷歌地图不是以HTML显示,而是在JS Fiddle上工作
- 正在尝试使用if和else添加类,但无法正常工作
- Jquery FadeIn FadeOut 只工作一次
- Foreach无法在Typescript中工作
- 另一个ajax调用中的Jquery ajax调用在for循环中没有按预期工作
- 为什么不是't窗口.恢复正常工作吗?(javascript/jquery)
- JS可以在Chrome中工作,但不能在Firefox中工作
- ajaxToolkit PopupControlExtender不工作.过时的
- HTML标记在脚本标记中工作
- 在JavaScript中的类中,push和concat的工作方式有何不同