简体   繁体   English

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

[英]Why passing function reference is failing while using function declaration is not?

Following code fails: 以下代码失败:

array.map(String.prototype.toLowerCase)

Throws Uncaught TypeError: String.prototype.toLowerCase called on null or undefined . 引发Uncaught TypeError: String.prototype.toLowerCase called on null or undefined Indeed, this is not set, I got it. 确实, this没有设置,我明白了。

But what's weird is that following code returns an array of empty strings without failing: 但是奇怪的是,以下代码返回了一个空字符串数组,但没有失败:

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

Any idea why? 知道为什么吗? Note that I know this is not the way of having an array of lowercased strings. 请注意,我知道这不是使用小写字符串数组的方式。 I'm just wondering why these two approaches behave differently. 我只是想知道为什么这两种方法的行为不同。

In other words, what is the difference between .map(String.prototype.toLowerCase) and .map((s) => String.prototype.toLowerCase(s)) ? 换句话说, .map(String.prototype.toLowerCase).map((s) => String.prototype.toLowerCase(s))什么区别? I thought is was identical, but obviously, it behaves differently. 我以为是相同的,但显然,它的行为有所不同。 Note that here, String.prototype.toLowerCase could be replaced by anything. 请注意,这里的String.prototype.toLowerCase可以替换为任何东西。

What is the difference between .map(String.prototype.toLowerCase) and .map((s) => String.prototype.toLowerCase(s)) .map(String.prototype.toLowerCase).map((s) => String.prototype.toLowerCase(s))之间有什么区别

For the first case when you get the function outside of an object (String.prototype.toLowerCase) you lose your context, so you context is null and map tries to call on null or undefined . 对于第一种情况,当您在对象(String.prototype.toLowerCase)之外获取函数时,您会丢失上下文,因此上下文为null,并且map尝试调用null or undefined With the first solution you can't get the desired result, because you need to pass a context to the toLowerCase function, which must be each item of the array , but you don't get that each item of array . 对于第一种解决方案,您无法获得理想的结果,因为您需要将上下文传递给toLowerCase函数,该函数必须是数组的每个项目 ,但是您不能得到array的每个项目

For the second case you need to pass context which is the item to the String.prototype.toLowerCase via call function. 对于第二种情况,您需要通过call函数将上下文 (即item传递给String.prototype.toLowerCase

 var array = ['ASD', 'BSD']; var lowered = array.map(item => String.prototype.toLowerCase.call(item)); console.log(lowered); 

The second approach array.map((s) => String.prototype.toLowerCase(s)) doesn't throw an error, because toLowerCase isn't taken out of context, ie the method still has String.prototype as its receiver. 第二种方法array.map((s) => String.prototype.toLowerCase(s))不会引发错误,因为toLowerCase并未脱离上下文,即该方法仍将String.prototype作为其接收者。

String.prototype.toLowerCase(s)) returns an empty string, because the argument s is discarded. String.prototype.toLowerCase(s))返回空字符串,因为参数s被丢弃。 toLowerCase takes it value from its receiving object instead. toLowerCase改为从其接收对象获取它的值。 The receiving object is String.protoype . 接收对象是String.protoype To get the actual string the prototype must be converted to string. 为了获得实际的字符串,必须将原型转换为字符串。 This happens with the String.prototype.toString method, which evaluates to "" . 这发生在String.prototype.toString方法中,其结果为"" Hence String.prototype.toLowerCase(s)) evaluates to "" . 因此, String.prototype.toLowerCase(s))计算结果为""

You can verify this behavior by changing the toString method: 您可以通过更改toString方法来验证此行为:

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

The diffrence between .map(String.prototype.toLowerCase) and .map((s) => String.prototype.toLowerCase(s)) is that .map((s) => String.prototype.toLowerCase(s)) takes an arrow function which is an anonymous function. .map(String.prototype.toLowerCase) and .map((s) => String.prototype.toLowerCase(s))之间的差异在于.map((s) => String.prototype.toLowerCase(s))需要箭头函数,它是一个匿名函数。 According to definition of arrow function " An arrow function expression has a shorter syntax than a function expression and does not bind its own this, arguments, super, or new.target. " An arrow function does not create its own this, the this value of the enclosing execution context is used. 根据箭头函数的定义“ 箭头函数表达式的语法比函数表达式短,并且不绑定其自身的this,arguments,super或new.target。 ”箭头函数不创建其自身的this,this值。使用封闭执行上下文。 using .map(String.prototype.toLowerCase) will not work as you are not passing any execution context to it but it's looking for one to execute. 使用.map(String.prototype.toLowerCase)无效,因为您没有向其传递任何执行上下文,而是在寻找要执行的上下文。 For example in the below code 例如下面的代码

function Person(){
  this.age = 0;

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

var p = new Person();

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

I think I got it finally: 我想我终于明白了:

  • first one has this set to undefined , equivalent to: 第一个将this设置为undefined ,等效于:
.map((s) => String.prototype.toLowerCase.call(undefined, s))
  • while second one has this set to String.prototype , equivalent to: 第二个将this设置为String.prototype ,等效于:
.map((s) => String.prototype.toLowerCase.call(String.prototype, s))

Now, the question is, why String.prototype.toLowerCase() is returning an empty string... But this deserves another question :) 现在,问题是,为什么String.prototype.toLowerCase()返回一个空字符串...但这值得另一个问题:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM