我目前正在从权威指南中学习javascript,许多代码示例使用xyx.call(undefined,/*args*/)
而不是仅仅将函数调用为xyz(/*args*/)
。
我知道如果执行上下文设置为undefined,那么this的值将引用全局对象。我无法弄清楚为什么在大多数示例中都这样做,因为它们不依赖于全局对象的值。任何人都可以帮助我理解其中的差异。
Array.protype.reduce的一些实现
if (!Array.prototype.reduce) {
Array.prototype.reduce = function(callbackfn, initialValue) {
"use strict";
var O = Object(this),
lenValue = O.length,
len = lenValue >>> 0,
k,
accumulator,
kPresent,
Pk,
kValue;
if (typeof callbackfn !== 'function') {
throw new TypeError();
}
if (len === 0 && initialValue === undefined) {
throw new TypeError();
}
k = 0;
if (initialValue !== undefined) {
accumulator = initialValue;
} else {
kPresent = false;
while(!kPresent && k < len) {
Pk = k.toString();
kPresent = O.hasOwnProperty(Pk);
if (kPresent) {
accumulator = O[Pk];
}
k += 1;
}
if (!kPresent) {
throw new TypeError();
}
}
while(k < len) {
Pk = k.toString();
kPresent = O.hasOwnProperty(Pk);
if (kPresent) {
kValue = O[Pk];
accumulator = callbackfn.call(undefined, accumulator, kValue, k, O);
}
k += 1;
}
return accumulator;
};
}
和一些用途:
if (!Array.prototype.reduce) {
Array.prototype.reduce = function(callback /*, initialValue*/) {
'use strict';
if (this == null) {
throw new TypeError('Array.prototype.reduce called on null or undefined');
}
if (typeof callback !== 'function') {
throw new TypeError(callback + ' is not a function');
}
var t = Object(this), len = t.length >>> 0, k = 0, value;
if (arguments.length == 2) {
value = arguments[1];
} else {
while (k < len && ! k in t) {
k++;
}
if (k >= len) {
throw new TypeError('Reduce of empty array with no initial value');
}
value = t[k++];
}
for (; k < len; k++) {
if (k in t) {
value = callback(value, t[k], k, t);
}
}
return value;
}; }
所以在一个方法中,回调函数使用call()调用,而在其他实现中则不是
答案 0 :(得分:1)
JavaScript是功能性OO语言。调用函数有不同的模式。 xyz(/*args*/)
和xyx.call(undefined,/*args*/)
是两种不同的调用。
xyz(/*args*/)
- 在这种情况下,this
有window
作为其值。
xyx.call(undefined,/*args*/)
- 在这种情况下,this
将只是我们在调用中传递的上下文,就像在这种情况下undefined
一样。
使用xyx.call(undefined,/*args*/)
只有特殊之处在于,您在函数调用中可以选择context
。当您编写面向对象的JavaScript时,context
的值很重要许多。这就是为什么使用xyx.call(undefined,/*args*/)
比xyz(/*args*/)
更明确的原因。
答案 1 :(得分:0)
您的示例使用调用数组函数的原因与JavaScript的多个(有些不必要的)数组类型有关。
除了在arr instanceof Array
上返回true的标准对象类型外,还有NodeList
函数和其他类似类型返回的document.querySelectorAll
。重要的是,这些其他类型没有所有Array的辅助函数( reduce,map,forEach )。
然而,他们仍然拥有技术上需要的所有功能;并且.call
方法可以帮助您做到这一点。所以,我们说我有两个系列。
var arr = [1,2,3];
var nodelist = document.querySelectorAll('.baby');
arr.map(function(val) { return val + 1; }); // Okay!
nodelist.map(function(val) { return val.innerHTML; }); // doesn't work
我可以使用call
在节点列表上拉出.map调用,为它提供一个不同的目标对象。
Array.prototype.map.call(nodelist, function...etc)
// Technically, this works too; just grabbing the method from our arr
// instance, but it's cleaner to refer to the original
// type's method.
arr.map.call(nodelist, function...etc)
解释您发布的代码示例;那些是&#34; polyfills&#34; - 浏览器应该有&#34;减少&#34;功能本身,但旧版浏览器可能没有。因此,我们自己创建它来复制相同的功能。