简体   繁体   中英

Why doesn't Javascript map function String.toLowerCase doesn't work in nodejs 6?

I'm going through the book Learning Javascript by Ethan Brown. There is an example on how to use the map function to convert all the elements in a array to lowercase like this:

const cart = [ { name: "Widget", price: 9.95 }, { name: "Gadget", price: 22.95 }];
const names = cart.map(x => x.name);
const lcNames = names.map(String.toLowerCase);

If I run this in the Firefox (v51) browser console, it works, however if I try to run this in nodejs v6.9.4 I get:

TypeError: undefined is not a function
    at Array.map (native)
    at repl:1:27
    at sigintHandlersWrap (vm.js:22:35)
    at sigintHandlersWrap (vm.js:96:12)
    at ContextifyScript.Script.runInThisContext (vm.js:21:12)
    at REPLServer.defaultEval (repl.js:346:29)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.<anonymous> (repl.js:545:10)
    at emitOne (events.js:101:20)

If I change the lcNames assignment to the following for nodejs then it runs fine:

const lcNames = names.map(x => x.toLowerCase());

I checked the ES6 Javascript compatibility chart for node6 vs Firefox 50 and they both seem to support the same features. So why doesn't the code from the book work in nodejs?

String.toLowerCase does not exist. However, String.prototype.toLowerCase does. But keep in mind that this would need to be set for that call to succeed, whereas map would pass it as a parameter . Hence, this is the most straightforward thing to do:

const lcNames = names.map(name => name.toLowerCase());

The function is defined on the prototype ( String.prototype.toLowerCase ), meaning that instances of the string type have access to the toLowerCase function.

That's why you can access that function via const lcNames = names.map(x => x.toLowerCase()); .

This on the other hand works, because isFinite is not defined through the prototype, but on Number itself.

const prices = cart.map(x => x.price);
prices.map(Number.isFinite);

Note that:

names.map(String.toLowerCase);

works in Firefox because it has String generic methods that include toLowerCase and are documented with the note:

String generics are non-standard, deprecated and will get removed near future. Note that you can not rely on them cross-browser without using the shim that is provided below.

Most important is that they aren't part of ECMAScript, so likely not supported in other browsers. If you want to use it, you can conditionally add a pollyfill, though there is a shim for adding all the generic methods at MDN .

 // Built-in support? console.log('Has built-in String.toLowerCase? ' + (typeof String.toLowerCase == 'function')); // Polyfill if not supported if (!String.toLowerCase) { String.toLowerCase = function(s) { return String(s).toLowerCase(); } } // Test it console.log(['A','B','C'].map(String.toLowerCase)) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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