sum(x,y)vs sun.call(undefined,x,y)之间的差异

时间:2015-02-17 17:03:36

标签: javascript

我目前正在从权威指南中学习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()调用,而在其他实现中则不是

2 个答案:

答案 0 :(得分:1)

JavaScript是功能性OO语言。调用函数有不同的模式。 xyz(/*args*/)xyx.call(undefined,/*args*/)是两种不同的调用。

xyz(/*args*/) - 在这种情况下,thiswindow作为其值。

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;功能本身,但旧版浏览器可能没有。因此,我们自己创建它来复制相同的功能。