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

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

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.

ES6 iterators and ##iterator [duplicate]

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.

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 .reduce used instead of reduce()? In flattening an array of arrays with JavaScript

This example is from http://eloquentjavascript.net/code/#5.1.
My question is the first bullet-pointed detail; others may be helpful details, but are additional; also see the first short program to see my question in context.
- Why is arrays.reduce() used instead of reduce(arrays()). I know that their's works with the arrays.reduce, but why?
This is an answer to a comment that is useful, but additional to the original question.
My question is with this first program. Since it uses arrays.reduce,
reduce would be a method of arrays, I am not sure why reduce is a
method of arrays. The reason might be in the design decisions of
JavaScript? Thanks, #cookie monster, for that comment!
This is the program with the context of my question-
var arrays = [[1, 2, 3], [4, 5], [6]];
console.log(arrays.reduce(function(flat, current) {
return flat.concat(current);
}, []));
// → [1, 2, 3, 4, 5, 6]
These next details are additional, but may(or may not) be of use:
I know that the [] at the end is used because it is the start parameter in the function reduce so that the other arrays are added to that empty array. I know the .concat is putting together the two arrays like + with strings, but for arrays. Here is what the reduce function, even though it is standard, looks like:
function reduce(array, combine, start){
var current = start;
for(var i = 0; i < array.length; i++)
current = combine(current, array[i]);
return current;
}
One of their other examples showed my way with a single array, if that helps. It looked like:
console.log(reduce([1, 2, 3, 4], function(a, b){
return a + b;
}, 0));
// 10
Thanks! :)
In object oriented design, a guiding principle is that you create or declare objects and those objects have a series of methods on them that operate on that particular type of object. As Javascript is an object oriented language, the built-in functions follow many of the object oriented principles.
.reduce() is a function that operates only on Arrays. It is of no use without an Array to operate on. Thus, in an object oriented design paradigm, it makes complete sense to place the .reduce() function as a method on an Array object.
This object-oriented approach offers the following advantages vs. a global reduce() function:
It is consistent with the object oriented principles used elsewhere in the language.
It is convenient to invoke the .reduce() function on a particular array by using array.reduce() and it is obvious from the syntax which array it is operating on.
All array operations are grouped as methods on the Array object making the API definition more self documenting.
If you attempt to do obj.reduce() (invoke it on a non-array), you will immediately get an runtime error about an undefined .reduce() method.
No additional space is taken in the global scope (e.g. no additional global symbol is defined - lessening the chance for accidental overwrite or conflict with other code).
If you want to know why anyone ever used a global reduce() instead, you would need to understand a little bit about the history of Javascript evolution. Before ES5 (or for users running browsers who hadn't yet implemented ES5 like IE8), Javascript did not have a built-in .reduce() method on the Array object. Yet, some developers who were familiar with this type of useful iteration capability from other languages wanted to to use it in their own Javascript or in their own Javascript framework.
When you want to add some functionality to an existing built-in object like Array in Javascript, you generally have two choices. You can add a method to the prototype (in object-oriented fashion) or you can create a global function that takes the Array as its first argument.
For the Array object in particular, there are some potential issues with adding iterable methods to the Array prototype. This is because if any code does this type of iteration of an array (a bad way to iterate arrays, but nevertheless done by many):
for (var prop in array)
they will end up iterating not only the elements of the array, but also any iterable properties of the array. If a new method is assigned to the prototype with this type of syntax:
Array.prototype.myMethod = function() {}
Then, this new method will end up getting iterated with the for (var prop in array) syntax and it will often cause problems.
So, rather than adding a new method to the prototype, a safer alternative was to just use a global function and avoid this issue.
Starting in ES 5.1, there is a way using Object.defineProperty() to add non-iterable methods to an object or prototype so for newer browsers, it is now possible to add methods to a prototype that are not subject to the problem mentioned above. But, if you wanted to support older browsers (like IE8) and use reduce() type of functionality, you're still stuck with these ancient limitations.
So ... even though a global reduce() is less object oriented and is generally not as desirable in Javascript, some older code went that route for legitimate safety/interoperability reasons. Fortunately, we are putting that road behind us as old version of IE drop off in usage (thank god for Microsoft dropping XP support to finally accelerate the demise of old versions of IE). And newer browsers already contain array.reduce() built in.
JavaScript was/is influenced by the language Scheme, a dialect of Lisp. In Scheme higher order functions are a key component/feature of the language. In fact the reduce function is pretty much equivalent to the fold function in Scheme. In the case of the reduce function in JavaScript, the creators of the language noticed that programmers often need to traverse arrays in a certain fashion, and gave programmers a higher order function where they can pass in a function to specify how they want to manipulate the data. Having higher order functions allows programmers to abstract redundant code therefore creating shorter, cleaner, more readable code.
You can use the reduce function in JavaScript to do many things other than flatten lists. Look here an example.

google closure compiler not renaming properties

I have an array of objects that I generate from JSON.parse. I access its properties like this:
AnObject['PhoneList'][i]['PhoneLabel']
When I run the code through the google closure compiler, the name of the properties is not obfuscated and clearly visible. Why are the names of object properties not obfuscated?
Google closure has a difficult time figuring out what it can and can't rename. For example, any data structure that is created or referenced by code outside the Google closure compiled code cannot be renamed or the two sides won't be expecting the same code. Further, referencing properties via constructed strings makes it next to impossible for closure to do it's job well. As such, Closure has a whole bunch of rules and settings to help you control this and direct it for what to do. I'd suggest you read up on those rules/settings at these references:
https://developers.google.com/closure/compiler/docs/api-tutorial3
https://developers.google.com/closure/compiler/docs/compilation_levels
https://groups.google.com/group/closure-stylesheets-discuss/browse_thread/thread/386ba6db27a43887?pli=1
https://developers.google.com/closure/compiler/docs/limitations
And, quoted from this last reference:
String representations of function or parameter names:
The Compiler renames functions and function parameters but does not
change any strings in your code that refer to functions or parameters
by name. You should thus avoid representing function or parameter
names as strings in your code. For example, the Prototype library
function argumentNames() uses Function.toString() to retrieve the
names of a function's parameters. But while argumentNames() might
tempt you to use the names of arguments in your code, Simple mode
compilation breaks this kind of reference.
Quoted strings is the syntax used for properties that should not be renamed ("exported").
you probably want to use
AnObject.PhoneList[i].PhoneLabel
instead.
Google Closure Compiler doesn't touch quoted strings.
myObj.prop = 3;
will result in prop being renamed (and myObj too perhaps)
myObj['prop'] = 3;
will result is 'prop' remaining untouched.

Categories