In a JS function, I'll be using an object resultModel, with two properties idArray and nameArray. What would be the proper way to declare this?
Currently I declare the object with var resultModel together with other variables at the top of the function, but the properties I simply start using by assigning them a value in a loop later in the function:
resultModel.idArray.push(someValue[i][0]);
resultModel.nameArray.push(someValue[i][1]);
Of course, I know that the var keyword is important for scoping, and as the "root" identifier is declared in the function I avoid any global tampering and this is all good. But I have an expectation that the properties of the value really should also be declared somehow, for other reasons than scoping - memory allocation springs to mind, possibly type hinting via JSDoc comments, readability and sheer completeness of declaration.
So, my question is: should I declare such properties, and what would in that case be the proper way to do that?
Like this:
var resultModel = {
idArray: [],
nameArray: []
};
Assignment is considerably slower than just putting the properties on the object in the first place, so this is the best way to go.
The objects in javascript are allocated memory dynamically ,like in a linked list so i do not think we should concern about the memory allocation here.
For better readability you could initialise them with null value like abhitalks mentioned above.
Put the property as a default value of same datatype .e.g for array -> Array(), for integers : 0 or -1 etc :
var resultModel = { "idArray": DEFAULT_VALUE , "nameArray" : DEFAULT_VALUE }
Related
So I learned a bit about the hidden class concept in v8. It is said that you should declare all properties in the constructor (if using prototype based "pseudo classes") and that you should not delete them or add new ones outside of the constructor. So far, so good.
1) But what about properties where you know the type (that you also shouldn't change) but not the (initial) value?
For example, is it sufficient to do something like this:
var Foo = function () {
this.myString;
this.myNumber;
}
... and assign concrete values later on, or would it be better to assign a "bogus" value upfront, like this:
var Foo = function () {
this.myString = "";
this.myNumber = 0;
}
2) Another thing is with objects. Sometimes I just know that an object wont have a fixed structure, but I want to use it as a hash map. Is there any (non verbose) way to tell the compiler I want to use it this way, so that it isn't optimized (and deopted later on)?
Update
Thanks for your input! So after reading your comments (and more on the internet) I consider these points as "best practices":
Do define all properties of a class in the constructor (also applies for defining simple objects)
You have to assign something to these properties, even if thats just null or undefined - just stating this.myString; is apparently not enough
Because you have to assign something anyways I think assigning a "bogus" value in case you can't assign the final value immediatly cannot hurt, so that the compiler does "know" ASAP what type you want to use. So, for example this.myString = "";
In case of objects, do assign the whole structure if you know it beforehand, and again assign dummy values to it's properties if you don't know them immediatly. Otherwise, for example when intending to use the Object as a hashmap, just do: this.myObject = {};. Think its not worth indicating to the compiler that this should be a hashmap. If you really want to do this, I found a trick that assigns a dummy property to this object and deletes it immediatly afterwards. But I won't do this.
As for smaller Arrays it's apparently recommended (reference: https://www.youtube.com/watch?v=UJPdhx5zTaw&feature=youtu.be&t=25m40s) to preallocate them especially if you know the final size, so for example: this.myArray = new Array(4);
Don't delete properties later on! Just null them if needed
Don't change types after assigning! This will add another hidden class and hurt performance. I think thats best practice anyways. The only case where I have different types is for certain function arguments anyways. In that case I usually convert them to the same target type.
Same applies if you keep adding additional properties later on.
That being said, I also think doing this will lean to cleaner and more organized code, and also helps with documenting.
Yeah, so one little thing I am unsure remains: What if I define properties in a function (for example a kind of configure() method) called within the constructor?
Re 1): Just reading properties, like in your first snippet, does not do anything to the object. You need to assign them to create the properties.
But for object properties it doesn't actually matter much what values you initialise them with, as long as you do initialise them. Even undefined should be fine.
The concrete values are much more relevant for arrays, where you want to make sure to create them with the right elements (and without any holes!) because the VM tries to keep them homogeneous. In particular, never use the Array constructor, because that creates just holes.
Re 2): There are ways to trick the VM into using a dictionary representation, but they depend on VM and version and aren't really reliable. In general, it is best to avoid using objects as maps altogether. Since ES6, there is a proper Map class.
Is there an elegant solution to destructure an object without specifying all the object's properties?
I wondered if it was possible to use the spread operator but it seems like that's not possible because objects are not arrays!
I guess it may be considered a bad idea to blindly declare variables but I think this would be useful for very large objects.
This is what the with(){} construction allowed:
var obj = {a: 1};
with (obj) {
console.log(a);
}
This construct is however severely discouraged and basically deprecated (it throws an error in strict mode), because it has some major drawbacks:
Your code is hard to read, because it's impossible to tell apart 1) Variables from outer scopes 2) Local variables 3) Properties coming from the object.
Your code can't be optimized, because the JavaScript engine can't tell where your variables are coming from.
Your code is much harder to refactor, because if you introduce a property to your obj, it might shadow some existing local variable, exemple:
var obj = {};
var a = 1;
addSomeProperties(obj);
with (obj) {
console.log(a); // the result here depends on whether or not "addSomeProperties" puts a property named "a" on "obj"
}
TL;DR version: you really don't want this, it makes your code brittle, hard to read&refactor. Just pick the pieces you want apart using the "normal" destructuring syntax.
I read this post, using delete keyword, we can delete JavaScript variable. But when I tried the same operations with constant but it is returning false when I try to delete constant. Is there any way to delete constants from memory?
I tried this answer but its also not working.
You can't directly do it, looking at the specs show us that the value can be set, but not over-written (such is the standard definition of a constant), however there are a couple of somewhat hacky ways of unsetting constant values.
Using scope
const is scoped. By defining the constant in a block it will only exist for this block.
Setting an object and unsetting keys
By defining const obj = { /* keys */ } we define a value obj that is constant, but we can still treat the keys like any other variable, as is demonstrated by the examples in the MDN article. One could unset a key by setting it to null.
If it's memory management that is the concern then both these techniques will help.
The delete operator is actually for deleting an object property, not a variable. In fact, in strict mode, delete foo is a syntax error.
Usually you can "delete" a value/object by removing all references to it, e.g. assigning null to a variable.
However, since constants are not writable (by definition) there is no way to do this.
As I wrote on my comment, delete can only be used on objects and arrays. So, what you can actually do is store all your constants in a constant object and free up memory by deleting it's properties, like this:
const myConstants = {};
myConstants.height = 100;
delete myConstants.height;
Would this piece of code work or is it counterproductive?
export default function freeObject(object) {
const keys = Object.keys(object)
for (const key of keys) {
delete object[key]
}
}
I used to store variables separately, for example, if I have an old element I would save it in a variable called "ele_old", and then later if I have a new element I would save that in a variable called "ele_new". However, it just occurred to me that I can save the 2 variables in 1 array variable, so I could do something like this:
eles_arr['old'] = //old element;
eles_arr['new'] = //new element;
this way would allow me to put variables of the same type into the same array for better organization, e.g. elements together in 1 array, and then ids together in another array.
The problem is I am quite new to javascript (and any other programming languages, for that matter), so I'm wondering if this is an inferior way than just keeping each variable separate. Will doing this cause any problems? for example, poor runtime performance?
Thanks!
What you're doing is setting properties on the eles_arr object. It's akin to saying:
eles_arr.oldEl = //old element
eles_arr.newEl = //new element
It's not storing them in an array, so it's similar to having the variables separated -- they're just grouped in the eles_arr object. To put them in an array you'd do:
eles_arr.push(oldEl);
eles_arr.push(newEl);
That being said I wouldn't put these two variables in an array. I would keep them separated to increase readability. It might make sense to you to have the values in the same array, and you may remember their positioning. Other developers may not though, which could lead to problems in the future.
Finally, having an array of two values for 'old' and 'new' will in no way affect performance in your case, but I still would not recommend using an array for readability's sake.
Update
I changed the variables from 'old' and 'new' to 'oldEl' and 'newEl' to reflect Šime's comment on the reserved keyword 'new'.
You can use an object to create a namespace / module, and so reduce the number of global / local variables:
var eles = {};
eles.foo = document.getElementById("foo");
eles.bar = document.getElementById("bar");
But that probably makes sense only if you have like 20 or more elements and you need them in various event handlers / functions. In that case, it makes sense to create the eles namespace and populate it with all your element references.
I just read this question and the accepted answer: What is JavaScript garbage collection?
In the answer, Noldorin referenced some guidelines from Apple. Here is the part I'm concerned with:
Use delete statements. Whenever you create an object using a new statement, pair it with a delete statement. This ensures that all of the memory associated with the object, including its property name, is available for garbage collection.
I'm always taking time to keep up-to-speed on best practices, especially if I can reduce the memory footprint of my scripts. So I went off to test some things. If I understand correctly, the following is an example of an object that deletes itself after invoking a method.
var thing = function () {
var a_method, and_another;
a_method = function() { /* do stuff */ };
and_another = function() { /* do some other stuff*/ };
this.init = function() { a_method(); and_another(); };
};
delete new thing().init();
Usually I'll wrap everything in a self invoking function and pass in my globals just like above. Everything is the same as I would normally do it, the only difference being that I added the delete right before the new.
The code works either way.
So the question is: Am I doing anything here? Is there some kind of benefit to deleting a reference to an object that only exists inside a function scope? Or am I just making things look confusing?
First of all the statement delete new scoped_object().init(); is not really doing anything, you should better take care about what variables remain in-closure or if you have circular references, which are the most common source of memory leaks.
The delete operator is meant to be used to delete object properties, and it is really misunderstood, the answer you quote from #Noldorin quotes some text of the Apple JavaScript "Best Practices", but they don't have a clue about how delete works!!.
They even recommend using delete on variable references, and that is not possible -only possible for variables declared in Eval Code-, because the var statement declares the variable as non-deletable ({DontDelete} in ECMAScript 3, or [[Configurable]] = false in ECMAScript 5) properties of the Variable Object -objects that form the scope chain-.
Moreover, attempting to delete a reference to an identifier that is bound to an environment record - an identifier declared with a VariableDeclaration, FunctionDeclaration or from a function's FormalParameterList-, causes a SyntaxError exception on the new ECMAScript 5th Edition under Strict Mode.
I would recommend you to read the following article about delete:
Understanding delete