TLDR below
I was reading through the Standard Built-In Objects portion of JavaScript on MDN and noticed that there are these methods that utilize 'Locale' and are used specifically, from what I can gather, to format return text from the method in a locally defined format if it exists. Apparently it causes an issue with Turkey(I don't know if there are others)
As far as I could tell, from what I've looked into, these were all implemented in ES 5.1 circa 2011. In fact, in one of the SO links in the references below it's actively pointed out that a reason why Angular 1.x might be using toString instead of toLocaleString is because of backwards compatibility with browsers that didn't yet completely adopt ES5.1 - simple aside: I don't know if that's exactly the case but it seems reasonable.
so I looked up the ES6 spec to check out the method:
On Object:
15.2.4.3 Object.prototype.toLocaleString ( ) This function returns the result of calling toString(). NOTE This function is provided to
give all Objects a generic toLocaleString interface, even though not
all may use it. Currently, Array, Number, and Date provide their own
locale-sensitive toLocaleString methods. NOTE The first parameter to
this function is likely to be used in a future version of this
standard; it is recommended that implementations do not use this
parameter position for anything else.
On Array:
15.4.4.3 Array.prototype.toLocaleString ( )
The elements of the array are converted to strings using their toLocaleString methods, and these strings are
then concatenated, separated by occurrences of a separator string that has been derived in an implementationdefined
locale-specific way. The result of calling this function is intended to be analogous to the result of
toString, except that the result of this function is intended to be locale-specific.
On String:
15.5.4.17 String.prototype.toLocaleLowerCase ( )
This function works exactly the same as toLowerCase except that its result is intended to yield the correct result
for the host environment’s current locale, rather than a locale-independent result. There will only be a difference in
the few cases (such as Turkish) where the rules for that language conflict with the regular Unicode case mappings.
NOTE The toLocaleLowerCase function is intentionally generic; it does not require that its this value be a String object.
Therefore, it can be transferred to other kinds of objects for use as a method.
NOTE The first parameter to this function is likely to be used in a future version of this standard; it is recommended that
implementations do not use this parameter position for anything else.
The original ToLowerCase for Clarity:
15.5.4.16 String.prototype.toLowerCase ( )
If this object is not already a string, it is converted to a string. The characters in that string are converted one by one
to lower case. The result is a string value, not a String object.
The characters are converted one by one. The result of each conversion is the original character, unless that
character has a Unicode lowercase equivalent, in which case the lowercase equivalent is used instead.
NOTE The result should be derived according to the case mappings in the Unicode character database (this explicitly includes
not only the UnicodeData.txt file, but also the SpecialCasings.txt file that accompanies it in Unicode 2.1.8 and later).
NOTE The toLowerCase function is intentionally generic; it does not require that its this value be a String object. Therefore, it
can be transferred to other kinds of objects for use as a method
(toLocaleUpperCase/toUpperCase reads exactly the same)
Given all that, and with the release of ES6 and it being largely adopted I am confused. I feel that toLowerCase and toUpperCase are used pretty commonly for validation purposes(though less so with ES6) and changing them to utilize Locale seems wrong because you would be checking against unknown formatting. So Okay, not really useful for validation. So what about outputting to the DOM with toLocaleString? It seems plausible, but again, you're dealing with unknowns. Say your locale isn't formatted and you wanted the integer 1000 to be displayed as '1,000'. (I've read that this happens with en-GB) It will leave it out of your hands and you may never even know that it's not displaying as you wanted it to.
TLDR:
Is there a practical use case for methods like toLocaleString toLocaleLowerCase toLocaleUpperCase, etc.? Should they be largely ignored?
Note: I realize this is on the line of opinionated, but I don't think it is. I'm looking for rational cases in which these may be applicable if they exist. e.g. like asking 'what you would use .call for' as opposed to 'do you think .call is better than .apply'
References
MDN String Prototype: toLocaleLowerCase
SO: Difference Between toLocaleLowerCase and toLowerCase?
SO: In which exactly js engines are toLowerCase toUpperCase locale sensitive?
SO: JavaScript difference between toString and toLocaleString methods of date?
It seems plausible, but again, you're dealing with unknowns.
Yes. You need to get to know them.
It will leave it out of your hands and you may never even know that it's not displaying as you wanted it to.
Indeed. If you want/need to have full control over your output, you need to implement the formatting yourself. If you only say, hey, it's a number, please format it to whatever you think is best for a British locale, then you can use it.
Is there a practical use case for methods like toLocaleString etc.?
Yes! You will want to use them in an environment that supports the ECMA-402 Standard.
From the API Overview:
"The ECMAScript 2016 Internationalization API Specification provides several key pieces of language-sensitive functionality that are required in most applications: String comparison (collation), number formatting, date and time formatting, and case conversion. While the ECMAScript 2016 Language Specification provides functions for this basic functionality (on Array.prototype: toLocaleString; on String.prototype: localeCompare, toLocaleLowerCase, toLocaleUpperCase; on Number.prototype: toLocaleString; on Date.prototype: toLocaleString, toLocaleDateString, and toLocaleTimeString), it leaves the actual behaviour of these functions largely up to implementations to define. The ECMAScript 2016 Internationalization API Specification provides additional functionality, control over the language and over details of the behaviour to be used, and a more complete specification of required functionality."
Should they be largely ignored?
In an unknown environment, probably. But not when you know what they do (because you control the environment, or you expect it to conform to ECMA-402), because in those cases they can be very useful and take a great deal of work off you.
Related
How does JavaScript represent strings and Date objects in memory?
Context and Intent
I'm mostly just curious, but here's what led to the question: We have code in our React front end that accepts JSON payloads from our API, and those payloads include dates -- in ISO-8601 UTC string form (e.g. 2023-02-01T17:01:08Z), of course.
As we pass the resulting model object around a variety of hooks, components, functions, etc., we keep it as a string, and we only parse it into a Date object if we are going to display it or use it to make decisions. In some cases, this means that we'll re-parse the same string into a Date multiple times in the course of rendering the UI. In other cases, we ignore the Date completely as it's not relevant for the page.
I'm trying to reason about whether it would be worthwhile to modify our system such that we always parse Date strings into actual Date objects upon receipt from our API. Our UI is written in TypeScript -- AFAIK this makes no difference with regard to my actual question -- and my biggest motivator in wanting to make this change is the improved type safety and clarity.
To be clear, time performance is the bigger concern, but I can do my own benchmarking. For the purposes of this question, I'm asking about memory performance, as much for my own understanding and education as for any technical decisions that might result, but I always try to understand the full scope of any tradeoff.
I imagine that this could be implementation dependent; if so, I'm most interested in the facts as they apply to modern versions of Google Chrome (with default configuration, if that matters), but happy to learn about other implementations as well.
Questions
If I take a 20-character ISO-8601 UTC string and parse it into a Date, how much memory would the resulting Date use? Does JavaScript work like Java, using an 8-byte "long" integer to store dates as milliseconds since the epoch? I found disappointingly little information about this in my searching; most of the results I found were actually about Java.
Also, how much memory does the string use? What's Javascript's internal string encoding? A quick Google indicates that it uses UTF-16 (and therefore 40 bytes for the 20-character date string)?
For both Date and String, are there any differences in applicable overhead? Are there optimizations that might apply to either Strings or Dates and affect the result (e.g. string interning -- which if I am understanding this correctly, JS does, but it would not apply to my use case since the value came from an API response)?
Let's say I use the URL interface to create a new URL. E.g. like that:
new URL('https://www.example.com/démonstration.html?query=6#bla')
Now I need this as a plain string. How do I best convert it?
Note: The examples here are minimal examples. I obviously don't convert a (hardcoded) string to an URL object and back to a string. To give some context, imagine I modify the URL object in between (possibly with user input) and/or pass it to different functions or so. In the end, I have an URL object and want it as a plain string.
I've found the following ways:
via href property:
(new URL('https://www.example.com/démonstration.html?query=6#bla')).href
// "https://www.example.com/d%C3%A9monstration.html?query=6#bla"
via toString method:
(new URL('https://www.example.com/démonstration.html?query=6#bla')).toString()
// "https://www.example.com/d%C3%A9monstration.html?query=6#bla"
As you can see, in my example, it returns exactly the same.
So looking at the doc you notice:
href is "a USVString containing the whole URL."
toString returns "a USVString containing the whole URL. It is a synonym for URL.href, though it can't be used to modify the value."
Okay, I don't want to modify it.
But are there really no differences? Maybe regarding performance, browser support¹ or even code style?
I have to decide for one, so which one should I choose?
¹ Actually I can see there are differences in the compatibility table for these conversion ways. So I guess there are also some legacy implementations that handle things differently or so. I cannot believe these are true "synonym" and this gab in browser support seems to support that believe.
According to the specification, they are doing exactly the same. The href attribute is marked up as a stringifier, which means that in JavaScript the class gets a toString method with exactly the same behaviour as the attribute.
As you have noticed, browser support is not the same for them. Also one is more to type and transmit than the other. This comes down entirely to preference. However, personally I find that an explicit toString call best conveys the message "I have an URL object and want it as a plain string."
The StandardAdditions.sdef indicates that particular data types can be retrieved from the clipboard using the key 'as'.
The clipboardInfo() function reveals what these keys are for Applescript, but is less eloquent in case of Yosemite JavaScript. (I haven't tried 10.11)
"text" and "string" seem to work, but none of the permutations which I have tried for public.html public.rtf «class HTML » «class RTF » rtf html etc. etc.
Has anyone found the keys that work here (assuming the presence of particular content types on the clipboard ?)
(In the meanwhile there are are, of course, some workable ObjC() alternatives for JXA:
ObjC.import('AppKit');
// Types: 'public.rtf', 'public.html' etc
function pboardUnpacked(strType) {
return ObjC.unwrap(
$.NSPasteboard.generalPasteboard.stringForType(
strType
)
)
}
// Types: 'com.apple.webarchive' etc
function pboardPlist(strType) {
return ObjC.deepUnwrap(
$.NSPasteboard.generalPasteboard.propertyListForType(
strType
)
)
}
but it would be good to have the briefer StandardAdditions idiom to hand as well ...
Four-char codes (aka OSType, aka UInt32) were/are fundamental building blocks in Apple event and other classic Mac OS APIs, where extreme compactness and machine efficiency were far more important than developer convenience or readability. (Mind, System 7 had to run on 8MHz 68030 boxes with a couple MB RAM.) Most of those old APIs have long since been taken out and shot, or at least heavily abstracted over by more modern ones (e.g. the UTI APIs don't just provide native UTI string support but also encapsulate all the old MIME-type and 4CC crap as well).
The only time the old crap leaks out is when using equally ancient crusty APIs like clipboard info which is horribly painful and obsolete nowadays. The fact that some of the type names returned by it appear as raw 4CCs in AS's 'chevron' syntax («class weba», «class RTF », etc. vs string, Unicode text) merely reflects the absence of a corresponding keyword for that code in AppleScript's own built-in dictionary (which is limited to the keyword-code mappings manually defined by the AS developers). And even if you do retrieve textual clipboard data in one of those alternative formats, it's usually useless to you anyway since AS can't do anything with data of that type anyway, unless you can find another equally ancient API that can also understand it.
The UTI system is capable and mature, and has been widely supported since 10.6 or so, so there's no reason not to use it when available, and plenty reason to avoid the ancient, gnarly, crippled schemes they've long since superseded. Doing otherwise is just making a rod for your own back: that such APIs still exist in AS merely reflects the AS team's failure to deprecate/modernize/replace them in pace with the rest of Apple; it's not a recommendation to use them.
..
As to the problems with JXA and symbolic AE types in general...
That JXA is incapable of representing 4CCs at all is due to its authors being dilettantes with no real-world experience in application automation and who repeatedly fail to dogfood their own technologies (Scripting Bridge, JXA, etc) or take expert advice from those of us who do.
In fact, JXA can't represent type and enum names - Unicode text, document, yes/no/ask etc. (i.e. values of type type class and constant) - at all. since JS doesn't have a native Symbol type, its authors thought they'd be clever and just use String, and have the bridge decide whether to pack those strings as typeType/typeEnum instead of typeUnicodeText descriptors before sending them in an Apple event based on what type of values the command's dictionary definition says is required.
This works in trivial cases, e.g. close saving [yes|no|ask], where the dictionary definition contains all the information required to determine the actual type required, but unsurprisingly falls apart as soon as you start to deal with more complex use cases where the required type cannot be inferred from the dictionary, or where the dictionary is insufficiently complete or correct. Someone with a deep understanding of AE technology would already realize this: application dictionaries' AETE/SDEF formats were never intended to be complete, comprehensive, accurate Interface Description Languages; merely translation tables for mapping human-readable names (aka 'application keywords') to and/or from the corresponding low-level 4CCs, and everything else is just there as user documentation, with no guarantee of completeness or correctness; thus trying to use the latter to do anything else is about as reliable as you'd expect.
Funny enough, the 10.11 prelease notes for JXA indicate they've disabled this 'magical' conversion behavior by default (no doubt because it was biting users in lots of other exciting ways that its authors failed to anticipate). There's no indication in those notes that they've added a Symbol class to represent AE type and enum names correctly in JS, so it should be fun to see what else breaks next.
The correct answer, found by mklement0, (see comments at end of question) is that JXA uses Apple's Uniform Type Identifier strings to identify the types of text held in the clipboard.
For example:
(function() {
ObjC.import('AppKit');
return ObjC.deepUnwrap(
$.NSPasteboard.generalPasteboard.pasteboardItems.js[0].types
);
})();
// e.g. -->
["public.rtf", "public.utf8-plain-text",
"public.utf16-external-plain-text", "dyn.ah62d4rv4gk81n65yru",
"com.apple.traditional-mac-plain-text", "dyn.ah62d4rv4gk81g7d3ru"]
I'd like to write a little library for JavaScript enums. For me to do that, I need to decide how to store the enum values. Therefore, I'd like to use the fastest way when comparing, but I also want something that is debuggable, so I'm torn between using strings or numbers. I know I could use objects too, but that would be another question
For example
// I don't want this because when debugging, you'd see just the value 0
var Planets = {Earth:0, Mars:1, Venus: 2}
// I'd prefer this so that Planets.Earth gives me a nice readable value ("Earth")
var Planets = {Earth: 'Earth', Mars: 'Mars'}
But I'm afraid that when I compare them using if (myPlanet === Planet.Earth), the string comparison could take a lot longer (say if it were in a tight loop). This should be the case because http://ecma-international.org/ecma-262/5.1/#sec-11.9.6 says
If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions); otherwise, return false.
But when I wrote a test case, I found that they take the same amount of time http://jsperf.com/string-comparison-versus-number-comparison/2 so it doesn't seem like it's scanning the whole string.
I know this could be a micro optimization, but my question is: is string equality comparison done using pointers and therefore just as fast as number equality comparison?
String comparison could be "just as fast" (depending on implementation and values) - or it could be "much slower".
The ECMAScript specification describes the semantics, not the implementation. The only way to Know for Certain is to create an applicable performance benchmark on run it on a particular implementation.
Trivially, and I expect this is the case1, the effects of string interning for a particular implementation are being observed.
That is, all string values (not String Objects) from literals can be trivially interned into a pool such that implIdentityEq("foo", "foo") is true - that is, there need only one string object. Such interning can be done after constant folding, such that "f" + "oo" -> "foo" - again, per a particular implementation as long as it upholds the ECMAScript semantics.
If such interning is done, then for implStringEq the first check could be to evaluate implIdentityEq(x,y) and, if true, the comparison is trivially-true and performed in O(1). If false, then a normal string character-wise comparison would need to be done which is O(min(n,m)).
(Immediate falseness can also be determined with x.length != y.length, but that seems less relevant here.)
1 While in the above I argue for string interning being a likely cause, modern JavaScript implementations perform a lot of optimizations - as such, interning is only a small part of the various optimizations and code hoistings that can (and are) done!
I've created an "intern breaker" jsperf. The numbers agree with the hypothesis presented above.
If a string is interned then comparison is approximate in performance to testing for "identity" - while it is slower than a numeric comparison, this is still much faster than a character-by-character string comparison.
Holding the above assertion, IE10 does not appear to consider object-identity for pass-fast string comparisons although it does use a fast-fail length check.
In Chrome and Firefox, two intern'ed strings which are not equal are also compared as quickly as two that are - there is likely a special case for comparing between two different interned strings.
Even for small strings (length = 8), interning can be much faster. IE10 again shows it doesn't have this "optimization" even though it appears to have an efficient string comparison implementation.
The string comparison can fail as soon as the first different character is encountered: even comparing long strings of equal length might only compare the first few characters.
Do common JavaScript implementations use string interning? (but no references given)
Yes. In general any literal string, identifier, or other constant string in JS source is interned. However implementation details (exactly what is interned for instance) varies, as well as when the interning occurs
See JS_InternString (FF does have string interning, although where/how the strings are implicitly interened from JavaScript, I know not)
There are cases when string comparison can be much slower (comparing dynamically generated strings)
The following is 77% slower (in chrome and IE) than all the other tests
var StringEarth = 'Ear' + 'th';
for (var i = 0; i < ITERATIONS; i++) {
x = StringPlanets.Venus === StringEarth;
}
The flaw in the tests mentioned in the question is the fact that we are testing against literal strings. It seems that JavaScript is optimized so that string comparison for string literals is done just by testing a pointer. This can be observed by creating the strings dynamically. My best guess is that strings from the literal string pool are marked so that they can be compared using addresses only.
Note that string comparison seems just as fast in FF even for dynamic strings. Also, that it's just as slow for even literal strings.
Conclusion All browsers behave differently so string comparison may or may not be slower.
In general, at best String interning (making a string with a given value into a unique reference or a O(1) comparable symbol) is going to take O(n) time, as it can't do that effectively without looking at all the characters involved.
The question of relative efficiency then amounts to over how many comparisons the interning is going to be amortized.
In the limit, a very clever optimizer can pull out static expressions which build up strings and intern them once.
Some of the tests above, use strings which will have been interned in which case the comparison is potentially O(1). In the case where enums are based on mapping to integers, it will be O(1) in any implementation.
The expensive comparison cases arise when at least one of the operands is a truly dynamic string. In this case it is impossible to compare equality against it in less than O(n).
As applied to the original question, if the desire is to create something akin to an enum in a different language, the only lookout is to ensure that the interning can is done in only a few places. As pointed out above, different Browser use different implementations, so that can be tricky, and as pointed out in IE10 maybe impossible.
Caveat lacking string interning (in which case you need the integer version of the enum implementation give), #JuanMendes' string-based enum implementations will be essentially O(1) if he arranges for the value of the myPlanet variable to be set in O(1) time. If that is set using Planets.value where value is an established planet it will be O(1).
A friend of mine drew my attention the welcome message of 4th European Lisp Symposium:
... implementation and application of
any of the Lisp dialects, including
Common Lisp, Scheme, Emacs Lisp,
AutoLisp, ISLISP, Dylan, Clojure,
ACL2, ECMAScript, ...
and then asked if ECMAScript is really a dialect of Lisp. Can it really be considered so? Why?
Is there a well defined and clear-cut set of criteria to help us detect whether a language is a dialect of Lisp? Or is being a dialect taken in a very loose sense (and in that case can we add Python, Perl, Haskell, etc. to the list of Lisp dialects?)
Brendan Eich wanted to do a Scheme-like language for Netscape, but reality intervened and he ended up having to make do with something that looked vaguely like C and Java for "normal" people, but which worked like a functional language.
Personally I think it's an unnecessary stretch to call ECMAScript "Lisp", but to each his own. The key thing about a real Lisp seems like the characteristic that data structure notation and code notation are the same, and that's not true about ECMAScript (or Ruby or Python or any other dynamic functional language that's not Lisp).
Caveat: I have no Lisp credentials :-)
It's not. It's got a lot of functional roots, but so do plenty of other non-lisp languages nowadays, as you pointed out.
Lisps have one remaining characteristic that make them lisps, which is that lisp code is written in terms of lisp data structures (homoiconicity). This is what enables lisps powerful macro system, and why it looks so bizzare to non-lispers. A function call is just a list, where the first element in the list is the name of the function.
Since lisp code is just lisp data, it's possible to do some extremely powerful stuff with metaprogramming, that just can't be done in other languages. Many lisps, even modern ones like clojure, are largely implemented in themselves as a set of macros.
Even though I wouldn't call JavaScript a Lisp, it is, in my humble opinion, more akin to the Lisp way of doing things than most mainstream languages (even functional ones).
For one, just like Lisp, it's, in essence, a simple, imperative language based on the untyped lambda calculus that is fit to be driven by a REPL.
Second, it's easy to embed literal data (including code in the form of lambda expressions) in JavaScript, since a subset of it is equivalent to JSON. This is a common Lisp pattern.
Third, its model of values and types is very lispy. It's object-oriented in a broad sense of the word in that all values have a concept of identity, but it's not particularly object-oriented in most narrower senses of the word. Just as in Lisp, objects are typed and very dynamic. Code is usually split into units of functions, not classes.
In fact, there are a couple of (more or less) recent developments in the JavaScript world that make the language feel pretty lispy at times. Take jQuery, for example. Embedding CSS selectors as a sublanguage is a pretty Lisp-like approach, in my opinion. Or consider ECMAScript Harmony's metaobject protocol: It really looks like a direct port of Common Lisp's (much more so than either Python's or Ruby's metaobject systems!). The list goes on.
JavaScript does lack macros and a sensible implementation of a REPL with editor integration, which is unfortunate. Certainly, influences from other languages are very much visible as well (and not necessarily in a bad way). Still, there is a significant amount of cultural compatibility between the Lisp and JavaScript camps. Some of it may be coincidental (like the recent rise of JavaScript JIT compilation), some systematic, but it's definitely there.
If you call ECMAScript Lisp, you're basically asserting that any dynamic language is Lisp. Since we already have "dynamic language", you're reducing "Lisp" to a useless synonym for it instead of allowing it to have a more specific meaning.
Lisp should properly refer to a language with certain attributes.
A language is Lisp if:
Its source code is tree-structured data, which has a straightforward printed notation as nested lists. Every possible tree structure has a rendering in the corresponding notation and is susceptible to being given a meaning as a construct; the notation itself doesn't have to be extended to extend the language.
The tree-structured data is a principal data structure in the language itself, which makes programs susceptible to manipulation by programs.
The language has symbol data type. Symbols have a printed representation which is interned: when two or more instances of the same printed notation for a symbol appear in the notation, they all denote the same object.
A symbol object's principal virtue is that it is different from all other symbols. Symbols are paired with various other entities in various ways in the semantics of Lisp programs, and thereby serve as names for those entities.
For instance, dialect of Lisp typically have variables, just like other languages. In Lisp, variables are denoted by symbols (the objects in memory) rather than textual names. When part of a Lisp program defines some variable a, the syntax for that a is a symbol object and not the character string "a", which is just that symbol's name for the purposes of printing. A reference to the variable, the expression written as a elsewhere in the program, is also an on object. Because of the way symbols work, it is the same object; this object sameness then connects the reference to the definition. Object sameness might be implemented as pointer equality at the machine level. We know that two symbol values are the same because they are pointers to the same memory location in the heap (an object of symbol type).
Case in point: the NewLisp dialect which has a non-traditional memory management for most data types, including nested lists, makes an exception for symbols by making them behave in the above way. Without this, it wouldn't be Lisp. Quote: "Objects in newLISP (excluding symbols and contexts) are passed by value copy to other user-defined functions. As a result, each newLISP object only requires one reference." [emphasis mine]. Passing symbols too, as by value copy, would destroy their identity: a function receiving a symbol wouldn't be getting the original one, and therefore not correctly receiving its identity.
Compound expressions in a Lisp language—those which are not simple primaries like numbers or strings—consist of a simple list, whose first element is a symbol indicating the operation. The remaining elements, if any, are argument expressions. The Lisp dialect applies some sort of evaluation strategy to reduce the expression to a value, and evoke any side effects it may have.
I would tentatively argue that lists being made of binary cells that hold pairs of values, terminated by a special empty list object, probably should be considered part of the definition of Lisp: the whole business of being able to make a new list out of an existing one by "consing" a new item to the front, and the easy recursion on the "first" and "rest" of a list, and so on.
And then I would stop right there. Some people believe that Lisp systems have to be interactive: provide an environment with a listener, in which everything is mutable, and can be redefined at any time and so on. Some believe that Lisps have to have first-class functions: that there has to be a lambda operator and so on. Staunch traditionalists might even insists that there have to be car and cdr functions, the dotted pair notation supporting improper lists, and that lists have to be made up of cells, and terminated by specifically the symbol nil denoting the empty list, and also a Boolean false. Insisting on car and cdr allows Scheme to be a Lisp, but nil being the list terminator and false rules
The more we shovel into the definition of "Lisp dialect", though, the more it becomes political; people get upset that their favorite dialect (perhaps which they created themselves) is being excluded on some technicality. Insisting on car and cdr allows Scheme to be a Lisp, but nil being the list terminator and false rules it out. What, Scheme not a Lisp?
So, based on the above, ECMAScript isn't a dialect of Lisp. However, an ECMAScript implementation contains functionality which can be exposed as a Lisp dialect and numerous such dialects have been developed. Someone who needs wants ECMAScript to be considered a Lisp for some emotional reasons should perhaps be content with that: that the semantics to support Lisp is there, and just needs a suitable interface to that semantics, which can be developed in ECMAScript and which can interoperate with ECMAScript code.
No it's not.
In order to be considered a Lisp, one has to be homoiconic, which ECMAscript is not.
Not a 'dialect'. I learned LISP in the 70's and haven't used it since, but when I learned JavaScript recently I found myself thinking it was LISP-like. I think that's due to 2 factors: (1) JSON is a list-like associative structures and (2) it's seems as though JS 'objects' are essentially JSON. So even though you don't write JS programs in JSON as you would write LISP in lists, you kind of almost do.
So my answer is that there are enough similarities that programmers familiar with LISP will be reminded of it when they use JavaScript. Statements like JS = LISP in a Java suit are only expressing that feeling. I believe that's all there is to it.
Yes, it is. Quoting Crockford:
"JavaScript has much in common with Scheme. It is a dynamic language. It has a flexible datatype (arrays) that can easily simulate s-expressions. And most importantly, functions are lambdas.
Because of this deep similarity, all of the functions in [recursive programming primer] 'The Little Schemer' can be written in JavaScript."
http://www.crockford.com/javascript/little.html
On the subject of homoiconicity, I would recommend searching that word along with JavaScript. Saying that it is "not homoiconic" is true but not the end of the story.
I think that ECMAScript is a dialect of LISP in the same sense that English is a dialect of French. There are commonalities, but you'll have trouble with assignments in one armed only with knowledge of the other :)
I find it interesting that only one of the three keynote presentations highlighted for the 4th European Lisp Symposium directly concerns Lisp (the other two being about x86/JVM/Python and Scala).
"dialect" is definitely stretching it too far. Still, as someone who has learned and used Python, Javascript, and Scheme, Javascript clearly has a far Lisp-ier feel to it (and Coffeescript probably even more so) than Python.
As for why the European Lisp Symposium would want to portray Javascript as a Lisp, obviously they want to piggyback on the popularity of the Javascript for which the programmer population is many, many times larger than all the rest of the Lisp dialects in their list combined.