Javascript pseudo-enum with IDE completion - javascript

Sometimes I need enum-like structures for fixed sets of string valus in Node.JS. Basically an object with keys for each enum value, and each value is a string equal to the key:
var State = {FOO: 'FOO', BAR: 'BAR', SOME_REALLY_LONG_NAME: 'SOME_REALLY_LONG_NAME'};
This enables me to type State.S and the IDE will suggest State.SOME_REALLY_LONG_NAME, and typos are practically eliminated. I can do if (x === State.FOO) etc.
The above syntax is however obviously not ideal due to the duplication of each literal during creation of the set of values. So I can do for example:
var State = _.indexBy(['FOO', 'BAR', 'SOME_REALLY_LONG_NAME'];
However, as soon as the object is created indirectly, the IDE (WebStorm in my case) will be unable to suggest/auto-complete the values. Sure, with JavaScript we're not very spoiled with working auto-complete anyway, but in my case it bugs me because the whole purpose of my "enum" is to simplify usage of a fixed set of strings.
There are also several enum utilities to create more proper enums, but they will suffer from the same thing. Also, if what I need is basically a fixed set of strings, more proper enums would force me into writing State.FOO.key to get the string value.
Is there a clever way to accomplish these really simple {key: 'key'} mappings without having to type each key twice during creation, but while still maintaining the IDE's understanding of which properties exist in the object? I'm guessing WebStorm only performs a static code analysis which goes out the window as soon as a function is called? Or is there some clever trick?

It's been a while that i used Webstorm, and it's macro-utilities, but maybe u can write a simple macro that expands your String-Array into the desired Structure.
Otherwise, you could try the Typescript-plugin. First of All: every valid JS should be valid TS (don't know exactly about ES7, and if some of the ES6 may bug the plugin).
But TS has a Enum-implementation and webstorm should therefore give you autocompletition and type-safety

Related

VS Code JS: Why / when do definitions break?

I use VS Code for JavaScript.
Definitions within a file work sometimes, but not others. Does anyone know why they fail?
In this example, VS Code finds the definition for edit easily. There is no occurrence of the word 'something' anywhere else in this file. Completely unique. So, why can't VS Code find its definition?
If I knew why, maybe I could change my code to work around it.
VS Code also can't find any references to these 'lost' properties. Which is very frustrating for tracking down where a function is called etc.
You should use this.
const edit = {
something: 5,
test() {
this.something;
},
};
You must not use an arrow function for test field, or this would point elsewhere but not the edit object.
EDIT: In TypeScript 4.3.5, the latest version of TS at the time of writing, TS is able to detect self-references in object literals, and both edit.something and this.something would work. For the case of working with JavaScript, upgrading VS Code should do the trick.
A TS playground link for reference.
There is a length limit. IntelliSense will define type :any if an object description is too long.
There is no way around this at all. The :any type will overwrite imported type definitions (e.g., a .d.ts file).
Two solutions:
Don't write long object declarations in your code.
Don't use VS Code or IntelliSense.
As for specifics:
The behavior is unpredictable.
If a type definition does not generate, reducing the object description length will not cause it to generate
Reducing an object description length to below the limit and re-launching VS Code will cause it to re-generate.
The length limit is unpredictable.
A function definition is 'longer' than a string, even if they have the same character count.
A nested ('deep') object declaration is longer than a shallow ('flat') object declaration, even if they have the same character count.
In short: IntelliSense breaks irreparably if you try to write long object declarations in a JS file.

What's the advantage of mapping a JavaScript string to a "constant"?

Looking through the Department of Better Technology's Formbuilder library, I see several cases of strings mapped to capital-letter object properties, as if imitating constants in JavaScript. The following is in main.coffee:
mappings:
SIZE: 'field_options.size'
UNITS: 'field_options.units'
LABEL: 'label'
FIELD_TYPE: 'field_type'
...
These "constants" are then mostly interpolated in strings that make up views. From paragraph.coffee:
view: """
<textarea class='rf-size-<%= rf.get(Formbuilder.options.mappings.SIZE) %>'></textarea>
"""
Is there a performance or architectural advantage in doing this, aside from not having to use literals? Seems like it would be less painstaking, if not faster, just to use the string.
Poor man's declaration safety.
rf.get('field_optons.size')
// => undefined (I assume, depends on rf.get)
rf.get(Formbuilder.optons.mappings.SIZE)
// => TypeError: Cannot read property 'mappings' of undefined
A typo in the first case lets your code proceed with a wrong value (undefined).
A typo in the second case, unless it is in the last component, will abort your program.
Javascript doesn't have constants so when you see this it is really more of a code convention used to communicate the intent of a constant. The primary advantage being that you can reference this constant ten times in your code and when you need the value to change, you only need to change it in one spot.
edit: constants are coming to ES6 and are now partially supported in varying browsers.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

Why JavaScript is giving access to override the existing properties in built-in object

Generally java-script allows to override (extend the new behavior) any function except those objects which are not frozen or seal. In JavaScript Math is a built-in object. But why JavaScript is giving access to override the existing properties in built-in object ?
Please find screenshot: Initially I find min function is available in Math Object. I have updated "min" property with function. This action replaced the existing code.
For more clarity I have deleted the property from "min". Here deletion should remove the extended behavior not the core one. But it is removing core property why?
Extending or modifying native code is called monkey-patching, and it's a design feature rather than a design flaw. Virtually everything is mutable and extensible in Javascript, and therefore you have the power to change fundamentals to suit your own needs (e.g. you could overload the min method so that it works with different variable types than just integers and floats), but with that power comes responsibility, so it's generally not advised to change these standard functions unless you know what you're doing; likewise, you have to be aware that if your JS file will be running on someone else's environment, you may not be able to rely on everything you think you can (however, you should generally be able to expect the usual global methods and properties, which is why you may call the global Object.prototype.keys or Array.prototype.slice rather than expect the method to be on the prototype of any one particular object).
In short, when you delete a function that you've modified, you will be deleting it entirely, not reverting it back to some sort of original state. You basically overwrote the original, and so there's no way of getting it back (except by deleting the code that overwrites it!).
Thanks to everyone for responding to my question. I got valuable information from everyone. myself did some analysis on this. I have gone through ECMA-262 Specification. I find some properties like 'E' in Math and their configurations.
According to specification document http://www.ecma-international.org/ecma-262/5.1/#sec-15.8.1
15.8.1.1 E
The Number value for e, the base of the natural logarithms, which is approximately 2.7182818284590452354.
This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.
Then I got to know some of properties of Math we can't delete because of 'Configurable' property.
When I executed following code, In retured object I find 'min' property of 'configurable: true'.
Object.getOwnPropertyDescriptor(Math, "min");
Object {value: function, writable: true, enumerable: false, configurable: true}
I agree with user162097 As he said 'it's a design feature rather than a design flaw.'
Thanks
No it is working correctly. delete function is deleting property from your Object. It doesn't know the object was original one or overridden, that's why overriding built in functions behavior is not best practice.
Instead of changing the native function behavior you can create yours in that object prototype, for instance lets create remove function for Array object:
Array.prototype.remove = function(member) {
var index = this.indexOf(member);
if (index > -1) {
this.splice(index, 1);
}
return this;
}
Nevertheless you can inherit from native objects, more about this you can read in this article-inheriting from native objects.
One nature of scripts is a fast prototyping. You may sort this abillity to a non-strict-declaration-aspect of javascript.

Strategy for handling case sensitivity of javascript properties

I'm sure someone is going to shout at me for asking this question, but here goes: in Javascript, what is the best strategy for coping with the fact that the properties of objects are case-sensitive? If I create an object with a property called FavouriteDrink, but then I later start referring to it as favouriteDrink then I could end up in a mess.
I don't want a big library here, but is there any way to define the object so that FavouriteDrink is defined somewhere, and where in Visual Studio 2012 some intellisense will help me choose the correct property name if I can somehow contextualise the object I'm dealing with? It is only properties I'm pondering here.
Thanks.
It doesn't work this way
if i look at your your code and see :
FavouriteDrink() {}
the first thing will popup in my mind is this is a constructor function not just a normal function
and by looking at this following one
favouriteDrink() {}
i would tell that this is a normal function and i can't use it as a constructor - can't be called with new
Here is some other examples
first_name // variable
FIRST_NAME // uppercase variables shouldn't change
_first_name // local variable not intended to be used out of its scope
var FIRSTNAME = {} // name space
it’s a good idea to follow a convention as to how the words will be separated
see this Code Conventions for the JavaScript Programming Language
For the other part of your question i'm using VS 2012 and i installed JSEnhancements
and i can see all my object element
JavaScript shares the following conventions with Java and ActionScript 3.
ALL_UPPERCASE
Use this as the variable name when you define a constant, or a value that should never change.
For example, myObject.NUM_TIMES_CLICKED = 2 would be a poor candidate for a constant because it is likely to change. However, myObject.APPLE_FRENCH_SPELLING = 'pomme' would be appropriate here.
firstWordLowercaseAndTheRestAllUppercase
Use this when you are defining anything that is not a constant or a class. You would use this for most things, for example, myObject.numTimesClicked, myObject.myFunction(), myObject.returnString.
AllWordsCapitalized
Use this when you are defining a function that defines a "class," generally any function you would call with the syntax myObject.myClassInstance = new MyClass(). Notice how myClassInstance is in camel-case because it is an instance of the class. However, MyClass is all caps because it is meant to be invoked with new.
You would define the class initially like this: myObject.MyClass = function(){};
WebStorm and Sublime Text are great tools that offer the code intelligence you're looking for.
WebStorm does this out of the box, but my personal preference is Sublime Text with the SublimeCodeIntel plugin.
That being said, it's probably best for you to be using naming conventions:
UpperCamelCase is for classes
ALL_CAPS_SNAKE_CASE is for constants
lowerCamelCase is used for everything else

Why would I need to freeze an object in JavaScript?

It is not clear to me when anyone would need to use Object.freeze in JavaScript. MDN and MSDN don't give real life examples when it is useful.
I get it that an attempt to change such an object at runtime means a crash. The question is rather, when would I appreciate this crash?
To me the immutability is a design time constraint which is supposed to be guaranteed by the type checker.
So is there any point in having a runtime crash in a dynamically typed language, besides detecting a violation better later than never?
The Object.freeze function does the following:
Makes the object non-extensible, so that new properties cannot be added to it.
Sets the configurable attribute to false for all properties of the object. When - configurable is false, the property attributes cannot be changed and the property cannot be deleted.
Sets the writable attribute to false for all data properties of the object. When writable is false, the data property value cannot be changed.
That's the what part, but why would anyone do this?
Well, in the object-oriented paradigm, the notion exists that an existing API contains certain elements that are not intended to be extended, modified, or re-used outside of their current context. The final keyword in various languages is the most suitable analogy of this. Even in languages that are not compiled and therefore easily modified, it still exists, i.e. PHP, and in this case, JavaScript.
You can use this when you have an object representing a logically immutable data structure, especially if:
Changing the properties of the object or altering its "duck type" could lead to bad behavior elsewhere in your application
The object is similar to a mutable type or otherwise looks mutable, and you want programmers to be warned on attempting to change it rather than obtain undefined behavior.
As an API author, this may be exactly the behavior you want. For example, you may have an internally cached structure that represents a canonical server response that you provide to the user of your API by reference but still use internally for a variety of purposes. Your users can reference this structure, but altering it may result in your API having undefined behavior. In this case, you want an exception to be thrown if your users attempt to modify it.
In my nodejs server environment, I use freeze for the same reason I use 'use strict'. If I have an object that I do not want being extended or modified, I will freeze it. If something attempts to extend or modify my frozen object, I WANT my app to throw an error.
To me this relates to consistent, quality, more secure code.
Also,
Chrome is showing significant performance increases working with frozen objects.
Edit:
In my most recent project, I'm sending/receiving encrypted data between a government entity. There are a lot of configuration values. I'm using frozen object(s) for these values. Modification of these values could have serious, adverse side effects. Additionally, as I linked previously, Chrome is showing performance advantages with frozen objects, I assume nodejs does as well.
For simplicity, an example would be:
var US_COIN_VALUE = {
QUARTER: 25,
DIME: 10,
NICKEL: 5,
PENNY: 1
};
return Object.freeze( US_COIN_VALUE );
There is no reason to modify the values in this example. And enjoy the benefits of speed optimizations.
Object.freeze() mainly using in Functional Programming (Immutability)
Immutability is a central concept of functional programming because without it, the data flow in your program is lossy. State history is abandoned, and strange bugs can creep into your software.
In JavaScript, it’s important not to confuse const, with immutability. const creates a variable name binding which can’t be reassigned after creation. const does not create immutable objects. You can’t change the object that the binding refers to, but you can still change the properties of the object, which means that bindings created with const are mutable, not immutable.
Immutable objects can’t be changed at all. You can make a value truly immutable by deep freezing the object. JavaScript has a method that freezes an object one-level deep.
const a = Object.freeze({
foo: 'Hello',
bar: 'world',
baz: '!'
});
When you're writing a library/framework in JS and you don't want some developer to break your dynamic language creation by re-assigning "internal" or public properties.
This is the most obvious use case for immutability.
With the V8 release v7.6 the performance of frozen/sealed arrays is greatly improved. Therefore, one reason you would like to freeze an object is when your code is performance-critical.
What is a practical situation when you might want to freeze an object?
One example, on application startup you create an object containing app settings. You may pass that configuration object around to various modules of the application. But once that settings object is created you want to know that it won't be changed.
This is an old question, but I think I have a good case where freeze might help. I had this problem today.
The problem
class Node {
constructor() {
this._children = [];
this._parent = undefined;
}
get children() { return this._children; }
get parent() { return this._parent; }
set parent(newParent) {
// 1. if _parent is not undefined, remove this node from _parent's children
// 2. set _parent to newParent
// 3. if newParent is not undefined, add this node to newParent's children
}
addChild(node) { node.parent = this; }
removeChild(node) { node.parent === this && (node.parent = undefined); }
...
}
As you can see, when you change the parent, it automatically handles the connection between these nodes, keeping children and parent in sync. However, there is one problem here:
let newNode = new Node();
myNode.children.push(newNode);
Now, myNode has newNode in its children, but newNode does not have myNode as its parent. So you've just broken it.
(OFF-TOPIC) Why are you exposing the children anyway?
Yes, I could just create lots of methods: countChildren(), getChild(index), getChildrenIterator() (which returns a generator), findChildIndex(node), and so on... but is it really a better approach than just returning an array, which provides an interface all javascript programmers already know?
You can access its length to see how many children it has;
You can access the children by their index (i.e. children[i]);
You can iterate over it using for .. of;
And you can use some other nice methods provided by an Array.
Note: returning a copy of the array is out of question! It costs linear time, and any updates to the original array do not propagate to the copy!
The solution
get children() { return Object.freeze(Object.create(this._children)); }
// OR, if you deeply care about performance:
get children() {
return this._PUBLIC_children === undefined
? (this._PUBLIC_children = Object.freeze(Object.create(this._children)))
: this._PUBLIC_children;
}
Done!
Object.create: we create an object that inherits from this._children (i.e. has this._children as its __proto__). This alone solves almost the entire problem:
It's simple and fast (constant time)
You can use anything provided by the Array interface
If you modify the returned object, it does not change the original!
Object.freeze: however, the fact that you can modify the returned object BUT the changes do not affect the original array is extremely confusing for the user of the class! So, we just freeze it. If he tries to modify it, an exception is thrown (assuming strict mode) and he knows he can't (and why). It's sad no exception is thrown for myFrozenObject[x] = y if you are not in strict mode, but myFrozenObject is not modified anyway, so it's still not-so-weird.
Of course the programmer could bypass it by accessing __proto__, e.g:
someNode.children.__proto__.push(new Node());
But I like to think that in this case they actually know what they are doing and have a good reason to do so.
IMPORTANT: notice that this doesn't work so well for objects: using hasOwnProperty in the for .. in will always return false.
UPDATE: using Proxy to solve the same problem for objects
Just for completion: if you have an object instead of an Array you can still solve this problem by using Proxy. Actually, this is a generic solution that should work with any kind of element, but I recommend against (if you can avoid it) due to performance issues:
get myObject() { return Object.freeze(new Proxy(this._myObject, {})); }
This still returns an object that can't be changed, but keeps all the read-only functionality of it. If you really need, you can drop the Object.freeze and implement the required traps (set, deleteProperty, ...) in the Proxy, but that takes extra effort, and that's why the Object.freeze comes in handy with proxies.
I can think of several places that Object.freeze would come in very handy.
The first real world implementation that could use freeze is when developing an application that requires 'state' on the server to match what's in the browser. For instance, imagine you need to add in a level of permissions to your function calls. If you are working in an application there may be places where a Developer could easily change or overwrite the permission settings without even realizing it (especially if the object were being passed through by reference!). But permissions by and large can never change and error'ing when they are changed is preferred. So in this case, the permissions object could be frozen, thereby limiting developer from mistakenly 'setting' permissions erroneously. The same could be said for user-like data like a login name or email address. These things can be mistakenly or maliciously broken with bad code.
Another typical solution would be in a game loop code. There are many settings of game state that you would want to freeze to retain that the state of the game is kept in sync with the server.
Think of Object.freeze as a way to make an object as a Constant. Anytime you would want to have variable constant, you could have an object constant with freeze for similar reasons.
There are also times where you want to pass immutable objects through functions and data passing, and only allow updating the original object with setters. This can be done by cloning and freezing the object for 'getters' and only updating the original with 'setters'.
Are any of these not valid things? It can also be said that frozen objects could be more performant due to the lack of dynamic variables, but I haven't seen any proof of that yet.
The only practical use for Object.freeze is during development. For production code, there is absolutely no benefit for freezing/sealing objects.
Silly Typos
It could help you catch this very common problem during development:
if (myObject.someProp = 5) {
doSomething();
}
In strict mode, this would throw an error if myObject was frozen.
Enforce Coding Protocol / Restriction
It would also help in enforcing a certain protocol in a team, especially with new members who may not have the same coding style as everyone else.
A lot of Java guys like to add a lot of methods to objects to make JS feel more familiar. Freezing objects would prevent them from doing that.
I could see this being useful when you're working with an interactive tool. Rather than:
if ( ! obj.isFrozen() ) {
obj.x = mouse[0];
obj.y = mouse[1];
}
You could simply do:
obj.x = mouse[0];
obj.y = mouse[1];
Properties will only update if the object isn't frozen.
Don't know if this helps, but I use it to create simple enumerations. It allows me to hopefully not get duff data in a database, by knowing the source of the data has been attempted to be unchangeable without purposefully trying to break the code. From a statically typed perspective, it allows for reasoning over code construction.
All the other answers pretty much answer the question.
I just wanted to summarise everything here along with an example.
Use Object.freeze when you need utmost surety regarding its state in the future. You need to make sure that other developers or users of your code do not change internal/public properties. Alexander Mills's answer
Object.freeze has better performance since 19th June, 2019, ever since V8 v7.6 released. Philippe's answer. Also take a look at the V8 docs.
Here is what Object.freeze does, and it should clear out doubts for people who only have surface level understanding of Object.freeze.
const obj = {
name: "Fanoflix"
};
const mutateObject = (testObj) => {
testObj.name = 'Arthas' // NOT Allowed if parameter is frozen
}
obj.name = "Lich King" // Allowed
obj.age = 29; // Allowed
mutateObject(obj) // Allowed
Object.freeze(obj) // ========== Freezing obj ==========
mutateObject(obj) // passed by reference NOT Allowed
obj.name = "Illidan" // mutation NOT Allowed
obj.age = 25; // addition NOT Allowed
delete obj.name // deletion NOT Allowed

Categories