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]
}
}
Related
When using a WeakMap Object in JavaScript, the get and set methods require a Key to be passed in as argument.
FYI, I'm using WeakMap to simulate private properties for a class, something like this:
window.MyObject = (function(){
let _privateProperty = new WeakMap();
class MyObject {
constructor(value) {
_privateVariable.set(this, value);
}
SamplePrivateGet() {
return _privateVariable.get(this);
}
}
return MyObject;
})();
My question is: is get and set performance influenced by the object used as key?
I know primitive types can't be used as key, but maybe using an object with only one property as key could be faster than using an object that has, say, one thousand properties.
I tried looking at ECMA specifications but it's not specified, my guess is it's because it would depends on the browser's implementation.
EDIT: There are two ways to approach this with WeakMaps, one is declaring a single _privateProperties WeakMap to which I will add my private properties, the other declare one WeakMap for each of the private properties. I'm currently using the second approach so that every WeakMap can be Garbage Collected separately, but maybe going with the first would allow me to make much less .get calls. But I guess that's out of the scope of the question :)
Not sure if this is good idea, but you could make kind of private instance properties by using Symbols.
const PRIVATE_VAR = Symbol('MY_CLASS::PRIVATE_VAR');
const PRIVATE_FUNC = Symbol('MY_CLASS::PRIVATE_FUNC');
export default class MyClass{
constructor(value){
this[PRIVATE_VAR] = value;
}
[PRIVATE_FUNC](){
/* ... */
}
}
Without access to those Symbols values, it is quite hard to access those specific instance properties (plus instance properties defined with Symbols are non-enumerable in classes and objects).
btw 'Private instance methods and accessors' are at stage 3 so such solutions might not be relevant soon
https://github.com/tc39/proposals
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.
Lets say I want to check whether a property exists within an Object or not. I was looking at two methods:
if(object.hasOwnProperty(key)) { /* do this */ }
OR
if(object[key]) { /* do this */ }
Assuming that we'll never have object = { key: false };
What are the tradeoffs of using one over the other ?
object[key] checks the entire object chain, including the prototype chain.
object.hasOwnProperty(key) checks to see if the key property is assigned directly to the object and does not look in the prototype chain.
So, which one to use depends upon which result you want.
See a simple demonstration using the hasOwnProperty property: http://jsfiddle.net/jfriend00/6zhv87rk/ which is on the prototype for an object.
You would typically use object.hasOwnProperty(key) when your key can be any arbitrary string and you want to make absolutely sure that it will never conflict with a built-in property on the Object prototype. In fact, if you really want to protect yourself, you even use this Object.prototype.hasOwnProperty.call(object, key) so even the hasOwnProperty property could be used with your object. Cases like this would be when you're using a Javascript object as a hash lookup or dictionary-type object with arbitrary key values.
You would typically use object[key] when you are not concerned about such a conflict because you know what types of keys will be on your object and you know they won't conflict because this version is just shorter and a bit easier to read.
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 }
Does the const keyword in JavaScript create an immutable reference to immutable data structures? [I'm assuming that immutable data structures exist in JavaScript.]
For string it appears to do so:
var x = "asdf";
const constantX = x;
alert("before mutation: " + constantX);
x = "mutated"
alert("after mutation: " + constantX);
output:
before mutation: asdf
after mutation: asdf
http://jsfiddle.net/hVJ2a/
first you aren't mutating the string, you're reassigning the reference.
You're right that const isn't available in all common browsers. But even if it were, it is not sufficient. const will prevent the reference from being reassigned - but if you have a const reference to a mutable object, you haven't accomplished very much.
const var o = { foo: 'bar' };
o = { foo: 'baz'}; // throws
o.foo = 'baz'; // allowed
So that brings us to your question, does js even have immutable data structures? No, js does not come with them. Immutable datastructures can be coded as a library - and assignment is not even defined, so o.foo = 'baz' doesn't even make sense. You have to write it as const var o2 = o.assoc('foo', 'baz') which will return a brand new object o2 instead of mutating o
But immutable data structures as a library doesn't mean much if nobody uses them. E.g. if angular uses regular javascript datastructures, you have to use them too. Otherwise you'd have to convert between mutable and immutable at the boundary between your code and angular.
opinion follows:
IMO your only practical options for doing real functional programming for production browser apps is to wait around for something like ClojureScript to mature. ClojureScript reboots the library ecosystem, so as libraries get written, they use immutable datastructures by default.
You can of course do half-baked functional programming in javascript using tools like underscore.js and Facebook React, which is what I do for the production webapps I build. But you have to establish immutability by convention, and people are going to mutate things on accident or because they don't know any better and you have to deal with those challenges.
Wrong. It is not immutable, from the MDN Documentation for const:
The const declaration creates a read-only reference to a value. It
does not mean the value it holds is immutable, just that the variable
identifier cannot be reassigned.
Yes, it does create an immutable reference, but it is not been standardized and is not supported in all browsers.
See this MDN article on the const keyword for details and compatability.
However, it doesn't do anything to set the referenced data structure as immutable. Several answers below address that question using, for example, Object.freeze
The only immutable data structure (something that is allocated on heap) is string. All other object alike things like objects, arrays and functions are mutable by default.
The const creates immutable variable. Yes, "const variable" sounds controversial but that is closest term I can come up with for JS.
The const content cannot be changed outside of its declaration. But it may contain reference, for example, to the object that is mutable by itself. So you can modify its properties through that const reference to it.
And if you want to make object to be immutable then there is a Object.freeze(obj) method.
You can create CONST like values using ES5 Object.defineProperty. The crummy part is that it must be bound to an object
CONSTS = {};
Object.defineProperty(CONSTS, 'FOO', {
value: 'bar'
});
CONSTS.FOO = 'derp' // Will throw error in strict mode
delete CONSTS.FOO // will throw error in strict mode
Yes that is right. A const would only declare a read-only named constant. Changing its value will have no effect.
Reference for const on MDN:
Const creates a constant that can be global or local to the function in which it is declared. Constants follow the same scope rules as variables.
The value of a constant cannot change through re-assignment, and a constant cannot be re-declared. Because of this, although it is possible to declare a constant without initializing it, it would be useless to do so.
A constant cannot share its name with a function or a variable in the same scope.
Here's the browser compatibility matrix.
const is a proposed feature of ECMAScript(together with a properly block-scoped let it is supposed to replace var and implicit global). ECMAScript Harmony is a grab-bag of ideas for the next versions of ECMAScript.
If you looking for read only variable, you can do like this
var constants = new (function() {
var x = 200;
this.getX = function() { return x; };
})();
You can use like this
constants.getX()
For example:
const basket = [1,2,3];
//Even though the variable is declared as const this one works
basket[0] = 1111;
console.log(basket);
//This one throws an error
basket = "Other primitive type."