为什么在使用函数声明时传递函数引用失败?

时间:2017-08-23 11:17:12

标签: javascript arrays function functional-programming

以下代码失败:

array.map(String.prototype.toLowerCase)

引发Uncaught TypeError: String.prototype.toLowerCase called on null or undefined。确实,this未设定,我明白了。

但奇怪的是,以下代码返回一个空字符串数组而不会失败:

array.map((s) => String.prototype.toLowerCase(s))

知道为什么吗? 请注意,我知道这不是使用小写字符串数组的方式。我只是想知道为什么这两种方法的行为不同。

换句话说,.map(String.prototype.toLowerCase).map((s) => String.prototype.toLowerCase(s))之间有什么区别?我认为是相同的,但很明显,它的表现不同。请注意,String.prototype.toLowerCase可以替换为任何内容。

4 个答案:

答案 0 :(得分:2)

  

.map(String.prototype.toLowerCase).map((s) => String.prototype.toLowerCase(s))之间有什么区别?   (String.prototype.toLowerCase)

对于第一种情况,当您在对象map之外获得该函数时,您将丢失上下文,因此您的上下文为空,null or undefined尝试调用toLowerCase。使用第一个解决方案,您无法获得所需的结果,因为您需要将上下文传递给item函数,该函数必须数组中的每个项目,但您不需要#39; t 数组的每个项目

对于第二种情况,您需要通过String.prototype.toLowerCase函数将call传递给上下文



var array = ['ASD', 'BSD'];

var lowered = array.map(item => String.prototype.toLowerCase.call(item));

console.log(lowered);




答案 1 :(得分:2)

第二种方法array.map((s) => String.prototype.toLowerCase(s))不会引发错误,因为toLowerCase不会脱离上下文,即该方法仍有String.prototype作为其接收方。

String.prototype.toLowerCase(s))返回一个空字符串,因为参数s被丢弃。 toLowerCase从接收对象中获取值。接收对象为String.protoype。要获取实际字符串,必须将原型转换为字符串。使用String.prototype.toString方法会发生这种情况,该方法的结果为""。因此String.prototype.toLowerCase(s))评估为""

您可以通过更改toString方法验证此行为:

String.prototype.toString = () => "FOO";
console.log(String.prototype.toLowerCase()); // "foo"

答案 2 :(得分:1)

.map(String.prototype.toLowerCase) and .map((s) => String.prototype.toLowerCase(s))之间的差异是.map((s) => String.prototype.toLowerCase(s))采用箭头函数,这是一个匿名函数。根据箭头功能的定义 “箭头函数表达式的语法比函数表达式短,并且不绑定它自己的参数,超级或new.target。” 箭头函数不会创建自己的this,使用封闭执行上下文的this值。 使用.map(String.prototype.toLowerCase)将无法正常工作,因为您没有向其传递任何执行上下文,但它正在寻找一个执行。 例如,在下面的代码中

function Person(){
  this.age = 0;

  setInterval(() => {
    this.age++; // |this| properly refers to the person object
  }, 1000);
}

var p = new Person();

请检查此链接 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

答案 3 :(得分:0)

我想我终于明白了:

  • 第一个将this设置为undefined,相当于:
.map((s) => String.prototype.toLowerCase.call(undefined, s))
  • 而第二个this设置为String.prototype,相当于:
.map((s) => String.prototype.toLowerCase.call(String.prototype, s))

现在,问题是,为什么String.prototype.toLowerCase()返回一个空字符串...但这值得另一个问题:)