2017-08-23 59 views
3

下面的代码失败:为什么传递函数引用失败,而使用函数声明不是?

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可以被任何东西取代。

回答

2

是什么.map(String.prototype.toLowerCase).map((s) => String.prototype.toLowerCase(s))

之间的区别对于第一种情况,当你得到函数的对象(String.prototype.toLowerCase)你失去了你的背景之外,所以你的上下文为null,并且map试图调用在null or undefined。使用第一种解决方案,您无法获得理想的结果,因为您需要将上下文传递给toLowerCase函数,该函数必须是阵列中的每个项目,但是您没有得到,即每个项目的数组

对于需要传递这是itemString.prototype.toLowerCase经由call功能的第二壳体上下文

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

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

 
console.log(lowered);

+0

这将无法工作既不并没有真正回答这个问题。换句话说,'.map(String.prototype.toLowerCase)'和'.map((s)=> String.prototype.toLowerCase(s))'有什么区别?我认为是相同的,但很明显,它的行为有所不同。 – sp00m

+0

查看编辑部分 –

+0

我认为这不完全正确,但它帮助我找出答案,所以谢谢;)基本上,国际海事组织,第一个有这个设置为undefined,而第二个设置为String.prototype。看到我自己的答案。 – sp00m

1

.map(String.prototype.toLowerCase) and .map((s) => String.prototype.toLowerCase(s))差异性之探源是.map((s) => String.prototype.toLowerCase(s))需要的箭头函数,它是一个匿名函数。根据箭头函数的定义 “箭头函数表达式的语法比函数表达式短,并且不绑定它自己的this,arguments,super或new.target。” “箭头函数不会创建它自己的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

+0

感谢您的回答,但我认为您错误地使用了“封闭执行上下文的这个值”。基本上,国际海事组织,首先有这个设置未定义,而第二个有这个设置为String.prototype。看到我自己的答案。 – sp00m

+0

你是对的,但我的意见与我在下面提供的示例代码有关,其中'this'是指Person类对象而不是全局窗口对象 – Niladri

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()将返回一个空字符串......但是,这值得另一个问题:)

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"

相关问题