ES6 iterators and ##iterator [duplicate] - javascript

I've noticed ## used in a few pages about new ES6 features, but I don't know what exactly it means (whether it's actually syntax or just some kind of documentation convention). And it's hard to google. Can someone explain it?

## describes what's called a well-known symbol. (Note that it isn't actually valid syntax in JS.) According to the ES6/ES20151 specification:
Well-known symbols are built-in Symbol values that are explicitly referenced by algorithms of this specification. They are typically used as the keys of properties whose values serve as extension points of a specification algorithm. Unless otherwise specified, well-known symbols values are shared by all Code Realms (8.2).
Code Realms refer to different instances of a JavaScript environment. For example, the Code Realm of the root document would be different to that of JavaScript running in an <iframe>.
An example of where it matter what code realm an object comes from is when trying to use instanceof to determine whether an object is an array (hint: it won't work if it's from another frame). To avoid these kinds of issues from popping up with symbols, they are shared so that references to (say) ##toString will work no matter where the object came from.
Some of these are exposed directly through the Symbol constructor, for example, ##toPrimitive is exposed as Symbol.toPrimitive. That can be used to override the value produced when attempting to convert an object to a primitive value, for example:
let a = { [Symbol.toPrimitive]: () => 1 };
console.log(+a); // 1
console.log(a.valueOf()); // (the same object)
console.log(a.toString()); // "[object Object]"
In general, symbols are used to provide unique properties on an object which cannot collide with a random property name, for example:
let a = Symbol();
let foo = { [a]: 1 };
foo[a]; // 1
There is no way to access the value except by getting the symbol from somewhere (though you can get all symbols for an object by calling Object.getOwnPropertySymbols, so they cannot be used to implement private properties or methods).
1: See this es-discuss topic for some discussion about the different names.

Related

What's the difference between str.fun() / str.fun / fun(str) in JavaScript?

I tried googling but couldn't find a precise answer, so allow me to try and ask here. If the question does not seem proper, please let me know and I'll delete it.
In JS you've got three different way of writing certain build in functionalities:
str.length
str.toString()
parseInt(str)
I wonder if there is a reason behind these different ways of writing. As a new user I don't grasp why it couldn't be streamlined as: length(str) / toString(str) / parseInt(str) or with dot formulation.
I however think if I do know the reason behind these differences, it would give me a better understanding of JavaScript.
Length is one of the attributes of string in JavaScript. Hence you use string.length to get the length of the string.
toString is a function for string objects, hence we use stringobj.toString().
parsInt(str) is a global function which takes string as a parameter.
JavaScript is object-oriented, so there are functions or procedures which require first an object to use as this in their bodies. str.length is a property, both syntactically and semantically. It doesn't require any parameters and represents some quality of the object. obj.toString() is a method (a function attached to an object), which doesn't represent any characteristics of the object, but rather operates on its state, computes some new values, or changes the state of the object a lot. parseInt(str) is a "global" function, which represents an operation not attached to any type or object.
Under the hood, these three ways may be well implemented with just calling a function, passing this as the first parameter (like C# does, for example). The semantic difference is the important one.
So why not use just the third syntax, like for example PHP does? First, it doesn't bloat the global environment with lots of functions which only work for one specific case and type, allowing you to specify any new function you want without breaking the old functionality. Second, it ecourages you to use object-oriented concepts, because you can already see working objects and methods in the language, and can try to make something similar.
And why isn't parseInt a method? It can as well be str.toInt() without any issues, it's just the way JavaScript designers wanted it to be, although it seems also a bit logical to me to make it a static method Number.parseInt(str), because the behaviour of the function is relevant more to the Number type than the String type.
JavaScript is based around objects. Objects have properties (e.g. a User object may have name and age properties). These are what define the user and are related to the user. Properties are accessed via dot-notation or brackets notation (to access Eliott’s age, we’ll use either eliott.age or eliott['age'] — these are equivalent).
These properties can be of any type — String, Number, Object, you name it — even functions. Now the proper syntax to call a function in JS is to put round brackets: eliott.sayHello(). This snippet actually fetches Eliott’s sayHello property, and calls it right away.
You can see Eliott as a box of properties, some of which can be functions. They only exist within the box and have no meaning out of the box: what would age be? Whose age? Who’s saying hello?
Now some functions are defined at the global level: parseInt or isNaN for instance. These functions actually belong to the global box, named window (because legacy). You can also call them like that: window.parseInt(a, 10) or window.isNaN(a). Omitting window is allowed for brevity.
var eliott = {
name: 'Eliott',
age: 32,
sayHello: function () { console.log('Hello, I’m Eliott'); }
};
eliott.name; // access the `name` property
eliott.age; // access the `age` property
eliott.sayHello; // access the `sayHello` property
eliott.sayHello(); // access the `sayHello` property and calls the function
sayHello(eliott); // Reference error: `window.sayHello` is undefined!
Note: Some types (String, Number, Boolean, etc.) are not real objects but do have properties. That’s how you can fetch the length of a string ("hello".length) and reword stuff ("hello, Eliott".replace("Eliott", "Henry")).
Behaviour of these expressions is defined in ECMAScript grammar. You could read the specification to understand it thoroughly: ECMAScript2015 specification. However, as pointed out by Bergi, it's probably not the best resource for beginners because it doesn't explain anything, it just states how things are. Moreover I think it might be too difficult for you to be able to grasp concepts described in this specification because of the very formal language used.
Therefore I recommend to start with something way simpler, such as a very basic introduction to JavaScript: JavaScript Basics on MDN. MDN is a great resource.
But to answer your question just briefly:
str.length is accessing a property of the str object.
parseInt(str) is a function call
str.toString() is a call of a function which is a property of the str object. Such functions are usually named methods.
Functions and methods are in fact very similar but one of the differences (except for the obvious syntax difference) is that methods by default have context (this) set to refer to the object which they're part of. In this case inside of toString function this equals to str.
Note: Accessing a property (as in str.length) could in effect call a getter function but it depends on how the object is defined, and is in fact transparent for the user.

Sharing native JavaScript objects across contexts in Nashorn

I have a Nashorn engine in which I evaluate some scripts that expose some common utility functions and objects. I want custom scripts to run in their own contexts and not step over each other, so I create new contexts for them using engine.createBindings():
ScriptContext newContext = new SimpleScriptContext();
newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
newContext.getBindings(ScriptContext.ENGINE_SCOPE).putAll(engine.getBindings(ScriptContext.ENGINE_SCOPE));
Now I have access to everything that was created in the original scope, but this also creates an entirely-new global-object for the new context, which means that instances of native JS objects like Object, Number, etc. are different from corresponding instances in the original context.
This leads to some strange behavior. For example, assume you have the following code that was evaluated in the engine (i.e., the "parent" context"):
function foo(obj) {
print(JSON.stringify(obj, null, 4));
print(Object.getPrototypeOf(obj) === Object.prototype);
}
Now let's say your custom script is as follows:
function bar() {
foo({a: 10, b: 20});
}
I evaluate this against newContext and then invoke the function:
engine.eval(source, newContext);
ScriptObjectMirror foo = newContext.getAttribute("foo", ScriptContext.ENGINE_SCOPE);
foo.call(null);
This returns:
undefined
false
This is expected behavior because objects created in other contexts are treated as foreign objects.
What I'm trying to do is to expose a common library of functions and maintain that within a single script-engine instance. I don't want to keep recreating script-engine instances because I end up losing JIT optimizations (I read this somewhere, but I can't find the link right now). I do like the fact that objects "remember" their originating global-context, but I'd like that not to happen in the case of native JS objects.
Is there a way to create an entirely-new global context, while still sharing JS global-object instances? I've tried manually copying over these instances (enumerating the properties of this), but when I copy them over to the new context, they are ScriptObjectMirror instances and not the unwrapped versions. I assume this is because they were originally created in a different context and therefore are considered to be "foreign".
It looks like it is not possible to do this unfortunately. I even unwrapped the objects and got back the native objects (I did this from the main thread), and then overwrote the ones in the new context. Unfortunately, this still doesn't work since the Java classes that represent native objects in Java maintain internal references to the original instances that were created (for prototypes of the object).
My workaround for the two cases above was to do this for the object test:
var proto = Object.getPrototypeOf(object);
return (typeof proto.constructor !== "undefined" && (proto.constructor.name === Object.prototype.constructor.name));
For JSON, I overwrote the native JSON object by evaluating Douglas Crockford's JSON library in the main context, and every new context. I did have to make some modifications to get it to work in Nashorn though. The first was to make it redefine the JSON object without check for its existence first (so just remove the if test). The second was to use the hasOwnProperty from the object itself as well, inside stringify. So the following line:
if (Object.prototype.hasOwnProperty.call(value, k))
Changes to:
if (Object.prototype.hasOwnProperty.call(value, k) || (value.hasOwnProperty && value.hasOwnProperty(k)))
With these two changes I was able to get things to work.

Understanding ES6 Symbols

I've been around the block when it comes to languages, having worked with everything from C# to Lisp to Scala to Haskell, and in every language that supported them, symbols have acted pretty much the same; that is, any two symbols with the same name, are guaranteed to be identical because they're singleton objects.
Racket: (equal? 'foo 'foo) true
Common Lisp: (eq 'foo 'foo) true
Ruby: :foo == :foo true
Scala: 'foo == 'foo true
ES6: Symbol('foo') === Symbol('foo') false
The benefit of symbols being singletons is obvious: You can use them in maps/dictionaries without risking your key not being equal to your input because the language suddenly decided to hash it differently (looking at you, Ruby)
So why is it that ECMAScript 6 takes a different approach on this, and how can I get around it?
You can (sort-of) get the effect of symbols being "knowable" by name by using registered (global) symbols:
var s1 = Symbol.for("foo");
var s2 = Symbol.for("foo");
s1 === s2; // true
Of course you can create your own Symbol registry too, with a Map instance or a plain object.
edit — I'll add that the intention of the optional string parameter when making a new Symbol instance is to provide a way of identifying the meaning and purpose of a symbol to the programmer. Without that string, a Symbol works just fine as a Symbol, but if you dump out an object in a debugger the properties keyed by such anonymous Symbol instances are just values. If you're keeping numeric properties on an object with Symbol keys, then you'll just see some numbers, and that would be confusing. The description string associated with a Symbol instances gives the programmer reference information without compromising the uniqueness of the Symbol as a key value.
Finally, you can always compare the result of calling .toString() on two similarly-constructed Symbol instances. I suspect that that practice would be considered questionable, but you can certainly do it.
edit more — it occurs to me that the fact that the default behavior of Symbol creation in JavaScript makes the type more useful than, say, atoms in Erlang or keys in Clojure. Because the language provides by default a value guaranteed to be unique, the fundamental problem of namespace collision is solved pretty nicely. It's still possible to work with "well-known" symbols, but having unique values available without having to worry about conflicts with other code that might also want to avoid collisions is nice. JavaScript has the somewhat unique, and certainly uniquely pervasive and uncontrollable, problem of a global namespace that may be polluted by code that a programmer does not even know exists, because code can collide in the browser enviroment due to the actions of a party different from, and unknown to, an arbitrary number of software architects.

Role of 'prototype' property amidst design of `function` type object?

As per the understanding, The main purpose for the existence of prototype property in a function type object is to allow properties/methods sitting under prototype to get inherited by other objects. This enables prototypical inheritance.
Considering window['Number'] function type object,
In general, Idea is to understand the thought process on what comes under prototype. So. I would like to take a specific example i.e., Number, with below questions.
From design perspective, how would I understand,
1)
why parseFloat()/parseInt()/isFinite()/isInteger()/isFinite()/isNaN()/NEGATIVE_INFINITY/NaN
are part of function type object Number?
2)
why methods toExponential()/toFixed()/toPrecision() are part of Number.prototype object?
Note: Have an idea on class based inheritance using java syntax, where both static/instance members can be inherited.
If you understand classic class based inheritance, then Number.parseFloat is a static class method, while Number.prototype.toFixed is an instance method. The "class methods" do not need an instance of Number to work, you simply call them directly as Number.parseFloat(foo). Instance methods on the other hand require an instance first:
var foo = new Number(bar);
foo.toFixed();
Properties declared on the prototype object are visible from all instances. Thus:
var n1 = new Number(1), n2 = new Number(2);
Those are two instances of Number, and via each instance it's possible to call the functions on the Number prototype:
alert( n2.toExponential() ); // "2e+0"
Because of the way that function invocation works in JavaScript, the .toExponential() function in that example will be invoked with this referring to the number instance used to make the function call — n2 in this case.
Now, the .toExponential() function could have been defined as a property of the Number constructor itself, but then the parameter would have to be passed explicitly (like Number.toExponential(2)). That's not how the runtime was designed, however. As with so many "why?" questions about how languages and APIs work, it's ultimately just a design preference on the part of the language designers. It should be clear that something like .parseFloat() would really not make any sense as a prototype method, because the whole point of .parseFloat() is to turn something that's not a number into a number. (It could have been added to one or more other prototype objects, but again the preference of the language designers was to just make it a callable function on the Number constructor itself; that's a recent ES6 addition to the spec of course.)
Finally note that in the particular case of the Number constructor, it's pretty rare that you'd actually explicitly instantiate a number object. Generally that happens implicitly when a number primitive value is used with the . or [ ] operators as if it were an object reference. Primitives are not objects, but the language automatically wraps a primitive value in a Number object in those cases, so the first example above would work the same if it were written like this:
var n2 = 2;
alert(n2.toExponential());
The variable n2 has a plain primitive 2 in it, but that will be wrapped in a Number instance in order to allow the method call.
I do not know whether you mean a program design perspective or a language (core library) design perspective, so I'll try to answer both.
Before we begin, please forget "class" or "instance" or "static".
JavaScript is not class based.
There only object and inheritance.
Now, let's see the object diagram.
Note that new Number does not inherits Number.
Neither prototype nor constructor is an inheriting relationship.
This means number instances inherits toExponential, toFixed, etc. but does not inherits parseFloat, parseInt etc.
So you call them like Number.parseFloat() and new Number(n).toFixed().
This is how JS is designed. If you don't like it you can design your own Number library.
For example, you may create your own Number that has toFixed methods on the Number object rather than on its prototype object, like this:
var SheepyNumber = {
toFixed: ( n ) => Number.toFixed( n )
}
SheepyNumber.toFixed( 3.14159265358979323846 ) // Evaluates to '3'
Do not add toFixed to Number object. It may work for now,
But if later specifications introduces this function with any different in parameter or logic,
then your program may break when you use the standard implementation,
or a third party library may break if you keep your own implementation.
Either way, you lost.
Which leave us the question, why does JS not put toFixed to Number, like we just did, but instead put toFixed to Number.prototype?
The obvious answer is this is more object-oriented.
Since new Number has an internal value property, toFixed can take that value, instead of taking in an extra argument.
The real answer is no one knows.
JavaScript copied Java for its core API - you can find most of these methods in the Java Float class.
Some of these Java methods are instance methods (corresponds to methods on Number.prorotype), some are static (corresponds to methods on Number), but most are both - including a counterpart of toFixed.
Why JavaScript did not put isFinite or isNaN to Number.prototype?
Why did no browsers implement toFixed on Number which can co-exists with the one on Number.prototype, during the first browser war that shaped the JavaScript as we know now?
Language design is an art.
And you may not always know who is responsible or why, because it has been shaped by many hands.

Why is arr = [] faster than arr = new Array?

I ran this code and got the below result. I curious to know why [] is faster?
console.time('using[]')
for(var i=0; i<200000; i++){var arr = []};
console.timeEnd('using[]')
console.time('using new')
for(var i=0; i<200000; i++){var arr = new Array};
console.timeEnd('using new')
using []: 299ms
using new: 363ms
Thanks to Raynos here is a benchmark of this code and some more possible way to define a variable.
Further expanding on previous answers...
From a general compilers perspective and disregarding VM-specific optimizations:
First, we go through the lexical analysis phase where we tokenize the code.
By way of example, the following tokens may be produced:
[]: ARRAY_INIT
[1]: ARRAY_INIT (NUMBER)
[1, foo]: ARRAY_INIT (NUMBER, IDENTIFIER)
new Array: NEW, IDENTIFIER
new Array(): NEW, IDENTIFIER, CALL
new Array(5): NEW, IDENTIFIER, CALL (NUMBER)
new Array(5,4): NEW, IDENTIFIER, CALL (NUMBER, NUMBER)
new Array(5, foo): NEW, IDENTIFIER, CALL (NUMBER, IDENTIFIER)
Hopefully this should provide you a sufficient visualization so you can understand how much more (or less) processing is required.
Based on the above tokens, we know as a fact ARRAY_INIT will always produce an array. We therefore simply create an array and populate it. As far as ambiguity, the lexical analysis stage has already distinguished ARRAY_INIT from an object property accessor (e.g. obj[foo]) or brackets inside strings/regex literals (e.g. "foo[]bar" or /[]/)
This is miniscule, but we also have more tokens with new Array. Furthermore, it's not entirely clear yet that we simply want to create an array. We see the "new" token, but "new" what? We then see the IDENTIFIER token which signifies we want a new "Array," but JavaScript VM's generally do not distinguish an IDENTIFIER token and tokens for "native global objects." Therefore...
We have to look up the scope chain each time we encounter an IDENTIFIER token. Javascript VMs contain an "Activation object" for each execution context which may contain the "arguments" object, locally defined variables, etc. If we cannot find it in the Activation object, we begin looking up the scope chain until we reach the global scope. If nothing is found, we throw a ReferenceError.
Once we've located the variable declaration, we invoke the constructor. new Array is an implicit function call, and the rule of thumb is that function calls are slower during execution (hence why static C/C++ compilers allow "function inlining" - which JS JIT engines such as SpiderMonkey have to do on-the-fly)
The Array constructor is overloaded. The Array constructor is implemented as native code so it provides some performance enhancements, but it still needs to check for arguments length and act accordingly. Moreover, in the event only one argument is supplied, we need to further check the type of the argument. new Array("foo") produces ["foo"] where as new Array(1) produces [undefined]
So to simplify it all: with array literals, the VM knows we want an array; with new Array, the VM needs to use extra CPU cycles to figure out what new Array actually does.
One possible reason is that new Array requires a name lookup on Array (you can have a variable with that name in scope), whereas [] does not.
Good question.
The first example is called an array literal. It is the prefered way to create arrays among many developers. It could be that the performance difference is caused by checking the arguments of the new Array() call and then creating the object, while the literal creates an array directly.
The relatively small difference in performance supports this point I think. You could do the same test with the Object and object literal {} by the way.
Also, interesting, if the length of the array is known in advance (elements will be added just after creation), the use of an array constructor with a specified length is much faster on recent Google Chrome 70+.
"new Array( %ARR_LENGTH% )" – 100% (faster)!
"[]" – 160-170% (slower)
The test can be found here - https://jsperf.com/small-arr-init-with-known-length-brackets-vs-new-array/2
Note: this result tested on Google Chrome v.70+; in the Firefox v.70 and IE both variants almost equal.
This would make some sense
Objects literals enable us to write code that supports lots of
features yet still make it a relatively straightforward for the
implementers of our code. No need to invoke constructors directly or
maintain the correct order of arguments passed to functions, etc.
http://www.dyn-web.com/tutorials/obj_lit.php

Categories