Why do objects use `Symbol.iterator`, instead of just `iterator` - javascript

Do objects use the property Symbol.iterator, instead of just iterator, to prevent us from overwriting the iterator property on the Object prototype?
If so, are there any other reasons?
Just trying to understand symbols in JS.

If it were just iterator, it could break old code that had objects with methods called iterator. Likewise, whenever the designers of JS want to let developers add other special methods to their objects, they would run the risk of clobbering existing names and breaking existing code.
An alternative is Python’s __double_underscore__ convention where developers are not supposed to defined methods named like this.

Related

Is there any disadvantage of using Map over Object in Javascript?

Are there any noticeable benefits of using Object over ES6's Map()? I like using it for the forEach function. Is it a bad practice to opt for Map() when needing hash tables?
The case of Object vs Map in the context of Javascript is more of a question of whether you want a generic or specialized tool for the job.
Map is actually just a special kind of object (just like any other type of object that you would construct in your application. You could even make your own Map() constructor function to mimic ES6 Maps). Like other objects, it has methods to access its functionalities. The "specialty" of the Map is to be an efficient key-value store.
The Object on the other hand is one of Javascripts native data types, and can be used for a variety of purposes (Map being one of them). It is not "specialized" for any one purpose.
So, in conclusion :
If you are using a Map as an efficient hash table, go for it! That's what it's built for.
If you are using Map for anything other than a key value store (or, as you say, just because of the forEach method) you may have to reconsider using it in favour of a more suitable data structure (which may or may not be a plain old object)
There is a good explanation on MDN as to when and why prefer Map over Object.
To sum it up:
Map has useful properties, utility functions and is Iterable, which
saves you some writing compared to using Object (like while trying to find number of key-value pairs)
Map can be more performant in intensive key-value operations (adition, removal)
Map prevents unwanted collisions between your keys and predefined Object's prototype properties
Map can use objects for keys

reducing repeated words after closure compiler

I need to reduce repeated words in a closure compiled js file manually, because i can't use gzip on the compiled js file.
I looked at a few ways to do it, for example I wanted to reduce the word "prototype" so what i did was a reference to the prototype in each object and then used that reference in order to add properties and methods to the object prototype, so the word prototype will be used only once for each object. But it seems that the closure compiler is having trouble with removing not used code this way in some cases, as it keeps methods in the object that are not been used by any object down the prototype chain or by this object itself.
it looks like it can't detect this way if the method is been used by any object down the prototype chain, so it keeps it and making the file size actually larger.
Another thing I tried to do in order to reduce the word "prototype" was using the #nocollapse annotation, but for some reason it breaks the code, the compiled code throws Uncaught ReferenceError about not defined variables and functions when I am trying to use this annotation, or it's just flatten the word, making it been repeated again.
Are there other ways in order to reduce repeated words?
thanks.
Closure compiler has an AliasStrings pass which will help significantly for cases where gzip is not used. It is not enabled nor exposed through a flag. Using it requires a custom build of the compiler.
https://github.com/google/closure-compiler/blob/master/src/com/google/javascript/jscomp/CompilerOptions.java#L442

extracting all used javascript variables

I have a big object defined in the global scope called global. I would like to dynamically find all the referenced properties under my variable global. That is, all the properties that were accessed during the execution of the code.
I want to do static code analysis to extract all the referenced properties under my variable. I can search for these patterns: global.PROPERTY_NAME AND global[PROPERTY_NAM]. However, what about the complicated cases like these ones
var tmp="PROPERTY_NAME";
global[tmp]
OR
var tmp=global;
tmp.PROPERTY_NAME
and the other ones?
I don't want to get all the variable's properties. I only want a list of the referenced ONES!! the properties that were referenced in my source code only
After your edit:
What you're looking for is JavaScript Proxy objects. Here is a tutorial on how to do this using them.
Proxy objects let you wrap an object and execute a method whenever its properties are accessed. Unfortunately as it currently stands they are not widely supported.
This is currently only way in JavaScript to accomplish this without changing your original global object.
You can turn them on in Chrome by enabling experimental JavaScript in the about:flags tab.
Before your edit:
The feature you're looking for is called reflection, JavaScript supports it well and natively
Here is some code that iterates through an object and gets its properties
for(var prop in global){
if(global.hasOwnProperty(prop)){ //this is to only get its properties and not its prototype's
alert(prop+" => "+global[prop]);
}
}
This is fairly cross-browser. More modern browsers allow you to do this in simpler ways like Object.keys(global) which returns an array containing all its enumerable properties, or Object.getOwnPropertyNames(global) which returns both enumerable and not-enumerable properties.
Due to the dynamic nature of JavaScript you won't achieve that with static code analysis. Think about cases like this:
var prop = document.getElementById('prop').value;
global[prop];
Impossible. The alternative, dynamic analysis, would mean that you modify your global object to log access to its properties, then run the code. This is easily possible in JavaScript but it won't help you either because how would you assure that you have covered every possible access? Especially in a 5 MB JavaScript, there are most likely edge cases that you will oversee.
So, if you can't narrow down your requirement, it won't be possible.

Why is there no forEach method on Object in ECMAScript 5?

ECMAScript 5's array.forEach(callback[, thisArg]) is very convenient to iterate on an array and has many advantage over the syntax with a for:
It's more concise.
It doesn't create variables that we need only for the purpose of iterating.
It's creates a visibility scope for the local variables of the loop.
It boosts the performance.
Is there a reason why there is no object.forEach to replace for(var key in object) ?
Of course, we could use a JavaScript implementation, like _.each or $.each but those are performance killers.
Well, it's pretty easy to rig up yourself. Why further pollute the prototypes?
Object.keys(obj).forEach(function(key) {
var value = obj[key];
});
I think a big reason is that the powers that be want to avoid adding built in properties to Object. Objects are the building blocks of everything in Javascript, but are also the generic key/value store in the language. Adding new properties to Object would conflict with property names that your Javascript program might want to use. So adding built in names to Object is done with extreme caution.
Array is indexed by integers, so it doesn't have this issue.
This is also why we have Object.keys(obj) instead of simply obj.keys. Pollute the Object constructor as that it typically not a big deal, but leave instances alone.
.forEach does create variables just for the purpose of iteration... Just not ones you create, yourself.
If you're using a shim, then they're JS variables in a closure, else they're likely in C++, or whatever the browser's native implementation is.
ES6 is getting for ... of which will iterate through whatever you pass it.
ES6 is also getting block-level variables (rather than function-scoped), using let, instead of var
You will be able to add iterators to specific kinds of objects in ES6 (ie: the objects you build to support iterators).
But the problem here is that ES5 was meant to preserve most of the syntax of ES3 (few new keywords, and no new keywords in regular-use).
Most of the additional functionality had to be method calls (prototyped, typically).
And arrays needed plenty of work, given how much more use JS has seen since ES3 launched.
Objects don't need a .map() / .reduce() ability, unless you're building VERY SPECIFIC objects, in which case, you're implementing those yourself.
You have to remember that every object in javascript inherits from Object. Not every object in javascript needs to have it's properties iterated. Those are mostly confined to data model objects. Adding the forEach method will only bulk up the prototype of every object unnecessarily.
If you currently see the Object and it's methods, they are present only to identify the object, or to distinguish one object from another.

Writing ECMAScript5 compliant code (Part 2)

I am currently learning advanced JavaScript, with an aim to build a standards compliant (HTML5, CSS3, ESv5) library. Along my way I have already asked a couple of related questions to try and figure out where to start, what to do, what not to do, what to avoid etc. I have already begun reading the ECMA-262 (ECMAScript version 5) documentation, and have been running a few tests before I get started on development work.
Previous questions:
Writing ECMAScript5 compliant code
What's the difference between JavaScript, JScript & ECMAScript?
In my research I found out that different browsers implement the standard differently, and in that respect, they implement different objects. For example, IE implements an object called ActiveXObject, but this is not the case in FireFox. So I wrote a little test facility which determines if something is defined within the browser.
Consider the following which tests a few known objects (including jQuery since this is not built in).
Again, I have reached a point where I am in need of help:
Questions:
Given the example above, what is the difference between an object and a function?
Do I write functions or objects in ES/JS?
Why is Object a function and not an object?
Is there any hierarchical structure to built in objects / functions?
Can built in objects / functions be redefined as something entirely different?
Can built in objects / functions be undefined?
Can built in objects / functions be assigned new features if they do not already support them natively?
If an object is defined in one browser and not another, how can I compensate for this?
P.S. I do not want answers relating to specific implementations (JavaScript/JScript), rather answers relating to the standard (ECMAScript v5). Thanks in advance!
Given the example above, what is the difference between an object and a function?
In Chrome, all these items are functions. In general however, a function is an object with the addition that it holds code and that you can call it. So, you can also just add properties to functions (like jQuery does: $("selector") or $.ajax).
Do I write functions or objects in ES/JS?
Well, obviously that depends on what you code. function() {} gives you a function; {} gives you an object. (Again, functions are objects in the end.)
Why is Object a function and not an object?
Object is a function because you can call it, either as a constructor or not:
Object(); // returns an empty object
new Object(); // same
Also, given that almost everything is an instance of Object, it follows that Object is a constructor and thus a function. (Note again that functions are also objects.)
Is there any hierarchical structure to built in objects / functions?
As for the ECMAScript built-in objects, there is in a sense. There are constructor functions (String) on the global object, functions for instances (Array.prototype.forEach), and "static" functions (Object.defineProperty which is meant to be used on objects, Array.isArray for arrays).
Can built in objects / functions be redefined as something entirely different?
Sure, you can do Object = null. But any code relying on Object will start throwing exceptions, so it's not recommended at all.
Can built in objects / functions be undefined?
No, an object is not undefined by definition. undefined is not an object and vice-versa. This holds for any object.
Can built in objects / functions be assigned new features if they do not already support them natively?
Yes, if e.g. Array.prototype.forEach does not exist, you could set it yourself. But it should be noted that such functions turn up in for(var key in arr) loops which again can cause code to behave differently. This can be solved using Object.defineProperty by using {enumerable: false}. But there is another caveat: the function is shared across the whole environment (e.g. the current page). If other code is also setting them you're experiencing collisions.
If an object is defined in one browser and not another, how can I compensate for this?
You can "shim" such functions. For e.g. ES5 functions such as Array.prototype.forEach there are shims available which make them available on older browsers as well. Underscore.js may be a good example.
Given the example above, what is the difference between an object and a function?
A function is just an object which is callable. However, I guess you ask for the types of host objects (Node, HTMLCollection etc): Their behaviour is implementation-dependent ("not ecmascript-native") - you can't rely on anything.
Do I write functions or objects in ES/JS?
Huh? You write code, which can be interpreted.
Why is Object a function and not an object?
Object is the native object constructor, and therefore a function (and also an Object).
Is there any hierarchical structure to built in objects / functions?
Do you ask for "Everything is an Object"? If you ask for the structure of DOM interfaces: They are implementation-dependent host objects again, but most implementors have a inheritance system based on the DOM specification.
Can built in objects / functions be redefined as something entirely different? Can built in objects / functions be undefined?
No. You can overwrite the global variables pointing to them (the properties of the global object), but every instance will nevertheless be constructed from the native (then [nearly] unaccessible) constructors.
Can built in objects / functions be assigned new features if they do not already support them natively? If an object is defined in one browser and not another, how can I compensate for this?
Yes, you can extend the native objects and their prototypes. But watch out for host objects, they might not like it. If an object is defined only in certain environments, you can easily test for its existance and possibly shim it (es5, html5).
As part of my research into ECMAScript / JavaScript, I have found the following resource which provides a lot of information regarding the JS DOM.
http://krook.org/jsdom/index-all.html

Categories