为什么' lodash.map(['A'], String.prototype.toLowerCase.

why `lodash.map(['A'], String.prototype.toLowerCase.call)` does not work?

本文关键字:String toLowerCase prototype lodash map 为什么      更新时间:2023-09-26

如果我想获得一个字符串数组转换为小写,这似乎是正常的事情:

lodash = require('lodash')
lodash.map(['A', 'B'], String.prototype.toLowerCase.call)
TypeError: object is not a function
    at Function.map (/Users/alejandro.carrasco/repos/cap-proxy/node_modules/lodash/dist/lodash.js:3508:27)
    at repl:1:9
    at REPLServer.self.eval (repl.js:110:21)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.EventEmitter.emit (events.js:95:17)
    at Interface._onLine (readline.js:202:10)
    at Interface._line (readline.js:531:8)
    at Interface._ttyWrite (readline.js:760:14)
    at ReadStream.onkeypress (readline.js:99:10)
    at ReadStream.EventEmitter.emit (events.js:98:17)

我在代码中挖掘了一点,似乎问题是由createCallback包装了在map中使用的传递函数产生的:

lodash.createCallback(String.prototype.toLowerCase.call)('A')
TypeError: object is not a function
    at repl:1:58
    at REPLServer.self.eval (repl.js:110:21)
    at Interface.<anonymous> (repl.js:239:12)
    at Interface.EventEmitter.emit (events.js:95:17)
    at Interface._onLine (readline.js:202:10)
    at Interface._line (readline.js:531:8)
    at Interface._ttyWrite (readline.js:760:14)
    at ReadStream.onkeypress (readline.js:99:10)
    at ReadStream.EventEmitter.emit (events.js:98:17)
    at emitKey (readline.js:1095:12)

但是我真的不明白那里发生了什么…

我知道它工作,如果我传递一个回调:

function(x) {return x.toLowerCase()}

为什么

['A', 'B'].map(String.prototype.toLowerCase.call)不工作的原因相同-它有效地使用Function.prototype.call.call(thisArg, currentValue)作为抛出TypeError: object is not a function的迭代器,因为您的thisArg是全局上下文(process)而不是String.prototype.toLowerCase

<标题> 如何
// You expect this to be your iterator:
String.prototype.toLowerCase.call('A');
// Instead, you got this:
String.prototype.toLowerCase.call.call(thisArg, 'A');

因为thisArg在你的例子中绑定到process,上面的行几乎相同:process()this绑定在'A'上。

// The "correct" invocation "should" be:
String.prototype.toLowerCase.call.call(String.prototype.toLowerCase, 'A');
<标题>修复h1> 可以通过传递"正确的"thisArg来修复它。以下是工作,但这样的map s并不比function(x) {return x.toLowerCase()}看起来更好对我来说:
['A'].map(String.prototype.toLowerCase.call, String.prototype.toLowerCase);
['A'].map(String.prototype.toLowerCase.call.bind(String.prototype.toLowerCase));
['A'].map(Function.prototype.call, String.prototype.toLowerCase);
['A'].map(Function.prototype.call.bind(String.prototype.toLowerCase));

upd随着ES2015和转译器的成熟,我更喜欢以下内容:

['A'].map(letter => letter.toLowerCase());

当您传递String.prototype.toLowerCase.call作为迭代器函数时,您实际上只是传递call函数,而没有上下文。

call函数的上下文通常是应该调用的函数。在这种情况下,似乎上下文被设置为某个对象(全局对象?),因此您得到错误object is not a function

一个可能的解决方案是将Function.call的上下文绑定到String.prototype.toLowerCase,如下所示:
_.map(['A', 'B'], Function.call.bind(String.prototype.toLowerCase));

或者更短一点:

_.map(['A', 'B'], Function.call.bind("".toLowerCase));

经过更多的测试,我发现以下代码可以使用下划线,但不能使用Lo-Dash,至少在浏览器中是这样的:

_.map(['A', 'B'], Function.call, "".toLowerCase);