How to declare string constants in JavaScript? [duplicate] - javascript

This question already has answers here:
Are there constants in JavaScript?
(33 answers)
Closed 6 years ago.
I want to declare string constants in JavaScript.
Is there is a way to do that?

Many browsers' implementations (and Node) have constants, used with const.
const SOME_VALUE = "Your string";
This const means that you can't reassign it to any other value.
Check the compatibility notes to see if your targeted browsers are supported.
Alternatively, you could also modify the first example, using defineProperty() or its friends and make the writable property false. This will mean the variable's contents can not be changed, like a constant.

Are you using JQuery? Do you want to use the constants in multiple javascript files? Then read on. (This is my answer for a related JQuery question)
There is a handy jQuery method called 'getScript'. Make sure you use the same relative path that you would if accessing the file from your html/jsp/etc files (i.e. the path is NOT relative to where you place the getScript method, but instead relative to your domain path). For example, for an app at localhost:8080/myDomain:
$(document).ready(function() {
$.getScript('/myDomain/myScriptsDir/constants.js');
...
then, if you have this in a file called constants.js:
var jsEnum = { //not really an enum, just an object that serves a similar purpose
FOO : "foofoo",
BAR : "barbar",
}
You can now print out 'foofoo' with
jsEnum.FOO

There's no constants in JavaScript, but to declare a literal all you have to do is:
var myString = "Hello World";
I'm not sure what you mean by store them in a resource file; that's not a JavaScript concept.

Of course, this wasn't an option when the OP submitted the question, but ECMAScript 6 now also allows for constants by way of the "const" keyword:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const
You can see ECMAScript 6 adoption here.

Standard freeze function of built-in Object can be used to freeze an object containing constants.
var obj = {
constant_1 : 'value_1'
};
Object.freeze(obj);
obj.constant_1 = 'value_2'; //Silently does nothing
obj.constant_2 = 'value_3'; //Silently does nothing
In strict mode, setting values on immutable object throws TypeError. For more details, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze

Well, you can do it like so:
(function() {
var localByaka;
Object.defineProperty(window, 'Byaka', {
get: function() {
return localByaka;
},
set: function(val) {
localByaka = window.Byaka || val;
}
});
}());
window.Byaka = "foo"; //set constant
window.Byaka = "bar"; // try resetting it for shits and giggles
window.Byaka; // will allways return foo!
If you do this as above in global scope this will be a true constant, because you cannot overwrite the window object.
I've created a library to create constants and immutable objects in javascript. Its still version 0.2 but it does the trick nicely. http://beckafly.github.io/insulatejs

Starting ECMAScript 2015 (a.k.a ES6), you can use const
const constantString = 'Hello';
But not all browsers/servers support this yet. In order to support this, use a polyfill library like Babel.

So many ways to skin this cat. You can do this in a closure. This code will give you a read-only , namespaced way to have constants. Just declare them in the Public area.
//Namespaced Constants
var MyAppName;
//MyAppName Namespace
(function (MyAppName) {
//MyAppName.Constants Namespace
(function (Constants) {
//Private
function createConstant(name, val) {
Object.defineProperty(MyAppName.Constants, name, {
value: val,
writable: false
});
}
//Public
Constants.FOO = createConstant("FOO", 1);
Constants.FOO2 = createConstant("FOO2", 1);
MyAppName.Constants = Constants;
})(MyAppName.Constants || (MyAppName.Constants = {}));
})(MyAppName || (MyAppName = {}));
Usage:
console.log(MyAppName.Constants.FOO); //prints 1
MyAppName.Constants.FOO = 2;
console.log(MyAppName.Constants.FOO); //does not change - still prints 1

You can use freeze method of Object to create a constant. For example:
var configObj ={timeOut :36000};
Object.freeze(configObj);
In this way you can not alter the configObj.

Use global namespace or global object like Constants.
var Constants = {};
And using defineObject write function which will add all properties to that object and assign value to it.
function createConstant (prop, value) {
Object.defineProperty(Constants , prop, {
value: value,
writable: false
});
};

Just declare variable outside of scope of any js function. Such variables will be global.

Related

Is there a way of listening/proxying a variable in vanilla Javascript?

I'm building a web framework, something like React; one of the things which I would like to improve on React is state.
My idea is something like Svelte, to use state you just create a normal variable (in my case it would be okay to use a function when creating te state, but not when updating it), but how Svelte does this Magic is by compiling, and I would like it to work in vanilla Javascript.
From my understanding this is not exactly possible, but I've still been trying to hack something somehow.
So the part of this state system that is not possible is knowing when a primitive is set and got (setters & getters), I want it to work with scoped variables; so I can't use the Object.defineProperty on the window or globalThis. I've been hacking around for quite some time and here are the only solutions I thought have could worked:
Proxing a new String(string), has given weird error of this beeing of the wrong type, unknows values, and stuff.
Proxing the Funtion.arguments object, but this didn't work.
Using Symbol.toPrimitive, but I couldn't find a way of using it without a + or ${}.
But as you can see they all have problems, I'm stuck and can't find anything, is there any (even if hacky, though without legacy or deprecated code) way to do this? Thank you!
You can't do what you've described in JavaScript. You can't proxy a primitive, and you can't run code some other way (getter, setter) when a variable is read or set, only when a property of an object is read or set.
There is an awful thing you can do in loose mode that's disallowed (for good reasons) in strict mode where you have an object with getters and setters that you then put into the environment used for resolving freestanding identifiers using the with statement, but again, it's disallowed for good reasons in strict mode (which is the default for modules and other mechanisms that create new contexts, like the body of a class).
I hesitate to give an example of it, but for completeness:
// This only works in loose mode, not strict mode
let a = 0;
const obj = {
get a() {
console.log(`Getter called, returning a = ${a}`);
return a;
},
set a(value) {
console.log(`Setter called, setting a = ${value}`);
a = value;
}
};
with (obj) {
console.log(a);
a = 42;
console.log(a);
}
Re your updated question:
My idea is something like Svelte, to use state you just create a normal variable...but how Svelte does this this Magic is by compiling, and I would like it to work in vanilla Javascript.
I wouldn't try to do it with freestanding variables, have the user provide a state object and convert its data properties to getter/setter combinations (or replace it with a new version with getter/setter combinations, etc.):
// Userland code provides a state object
const state = {
a: 0,
b: "hi",
};
// Your framework code converts it to using getters/setters
function enhance(obj) {
const descrs = Object.getOwnPropertyDescriptors(obj);
for (const key of Object.keys(descrs)) {
const descr = descrs[key];
if (descr.configurable && "value" in descr && typeof descr.value !== "function") {
// A simple data property; wrap it in getter/setter
let value = descr.value;
if (typeof value === "object") {
enhance(value);
} else {
Object.defineProperty(obj, key, {
get() {
console.log(`Getter called, returning ${key} = ${value}`);
return value;
},
set(newValue) {
console.log(`Setter called, setting ${key} = ${newValue}`);
value = newValue;
},
enumerable: descr.enumerable,
configurable: true,
});
}
}
}
}
enhance(state);
// Their code using the properties triggers your getter/setters:
console.log(state.a, state.b);
state.a = 42;
state.b = state.b.toUpperCase();
console.log(state.a, state.b);

Convert var to const javascript

Is it possible to convert a var to a const?
Say in a scenario like this:
var appname = ''
function setAppName(name) {
appname = name // can I convert this to const now?
}
Basically, this is for a parameter level. Parameter needs to be accessible throughout the file and I want to make it const after first assignment. Is this possible?
To add: If there is any other way besides creating an object with to contain this parameter, it would be better (for a more straightforward solution). I will be working on multiple parameters like this and freezing an object will cause the entire object to freeze. I am hoping to do this on the parameter level.
So either change the parameter to become const. OR (this one I dont think is possible) change the scope of the paramter to global:
function setAppName(name) {
const appname = name // can I change the scope and make this global?
}
Thanks.
Put your app name in an object and freeze it.
let appSettings = { name: "" };
function setAppName(name) {
appSettings.name = name;
Object.freeze(appSettings);
}
Freezing prevents adding, removing and modifying the values of the properties in your object so you should call Object.freeze only once after all other settings (if there are more variables you want to make constant) have been set.
You can do this using a object.
const globals = {
appname: ''
}
function setAppName(name) {
globals.appname = name;
Object.freeze(globals)
// After this point, value of appname cannot be modified
}
Thank you for all your inputs.
I was able to find a workaround for what I was trying to achieve.
var appname = ''
function setAppName(name) {
if (appname === '') {
appname = name // can I convert this to const now?
}
}
Although this doesnt convert it to const, I just added a guard on the setter and it will not be able to overwrite the value now (unless otherwise I am going to initialize again to an empty string).
It is not fool-proof, but this will address my need.
Thanks all!

javascript: prototype in javascript like reflection in c#, is it possible? [duplicate]

In Ruby I think you can call a method that hasn't been defined and yet capture the name of the method called and do processing of this method at runtime.
Can Javascript do the same kind of thing ?
method_missing does not fit well with JavaScript for the same reason it does not exist in Python: in both languages, methods are just attributes that happen to be functions; and objects often have public attributes that are not callable. Contrast with Ruby, where the public interface of an object is 100% methods.
What is needed in JavaScript is a hook to catch access to missing attributes, whether they are methods or not. Python has it: see the __getattr__ special method.
The __noSuchMethod__ proposal by Mozilla introduced yet another inconsistency in a language riddled with them.
The way forward for JavaScript is the Proxy mechanism (also in ECMAscript Harmony), which is closer to the Python protocol for customizing attribute access than to Ruby's method_missing.
The ruby feature that you are explaining is called "method_missing" http://rubylearning.com/satishtalim/ruby_method_missing.htm.
It's a brand new feature that is present only in some browsers like Firefox (in the spider monkey Javascript engine). In SpiderMonkey it's called "__noSuchMethod__" https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/NoSuchMethod
Please read this article from Yehuda Katz http://yehudakatz.com/2008/08/18/method_missing-in-javascript/ for more details about the upcoming implementation.
Not at the moment, no. There is a proposal for ECMAScript Harmony, called proxies, which implements a similar (actually, much more powerful) feature, but ECMAScript Harmony isn't out yet and probably won't be for a couple of years.
You can use the Proxy class.
var myObj = {
someAttr: 'foo'
};
var p = new Proxy(myObj, {
get: function (target, methodOrAttributeName) {
// target is the first argument passed into new Proxy, aka. target is myObj
// First give the target a chance to handle it
if (Object.keys(target).indexOf(methodOrAttributeName) !== -1) {
return target[methodOrAttributeName];
}
// If the target did not have the method/attribute return whatever we want
// Explicitly handle certain cases
if (methodOrAttributeName === 'specialPants') {
return 'trousers';
}
// return our generic method_missing function
return function () {
// Use the special "arguments" object to access a variable number arguments
return 'For show, myObj.someAttr="' + target.someAttr + '" and "'
+ methodOrAttributeName + '" called with: ['
+ Array.prototype.slice.call(arguments).join(',') + ']';
}
}
});
console.log(p.specialPants);
// outputs: trousers
console.log(p.unknownMethod('hi', 'bye', 'ok'));
// outputs:
// For show, myObj.someAttr="foo" and "unknownMethod" called with: [hi,bye,ok]
About
You would use p in place of myObj.
You should be careful with get because it intercepts all attribute requests of p. So, p.specialPants() would result in an error because specialPants returns a string and not a function.
What's really going on with unknownMethod is equivalent to the following:
var unk = p.unkownMethod;
unk('hi', 'bye', 'ok');
This works because functions are objects in javascript.
Bonus
If you know the number of arguments you expect, you can declare them as normal in the returned function.
eg:
...
get: function (target, name) {
return function(expectedArg1, expectedArg2) {
...
I've created a library for javascript that let you use method_missing in javascript: https://github.com/ramadis/unmiss
It uses ES6 Proxies to work. Here is an example using ES6 Class inheritance. However you can also use decorators to achieve the same results.
import { MethodMissingClass } from 'unmiss'
class Example extends MethodMissingClass {
methodMissing(name, ...args) {
console.log(`Method ${name} was called with arguments: ${args.join(' ')}`);
}
}
const instance = new Example;
instance.what('is', 'this');
> Method what was called with arguments: is this
No, there is no metaprogramming capability in javascript directly analogous to ruby's method_missing hook. The interpreter simply raises an Error which the calling code can catch but cannot be detected by the object being accessed. There are some answers here about defining functions at run time, but that's not the same thing. You can do lots of metaprogramming, changing specific instances of objects, defining functions, doing functional things like memoizing and decorators. But there's no dynamic metaprogramming of missing functions as there is in ruby or python.
I came to this question because I was looking for a way to fall through to another object if the method wasn't present on the first object. It's not quite as flexible as what your asking - for instance if a method is missing from both then it will fail.
I was thinking of doing this for a little library I've got that helps configure extjs objects in a way that also makes them more testable. I had seperate calls to actually get hold of the objects for interaction and thought this might be a nice way of sticking those calls together by effectively returning an augmented type
I can think of two ways of doing this:
Prototypes
You can do this using prototypes - as stuff falls through to the prototype if it isn't on the actual object. It seems like this wouldn't work if the set of functions you want drop through to use the this keyword - obviously your object wont know or care about stuff that the other one knows about.
If its all your own code and you aren't using this and constructors ... which is a good idea for lots of reasons then you can do it like this:
var makeHorse = function () {
var neigh = "neigh";
return {
doTheNoise: function () {
return neigh + " is all im saying"
},
setNeigh: function (newNoise) {
neigh = newNoise;
}
}
};
var createSomething = function (fallThrough) {
var constructor = function () {};
constructor.prototype = fallThrough;
var instance = new constructor();
instance.someMethod = function () {
console.log("aaaaa");
};
instance.callTheOther = function () {
var theNoise = instance.doTheNoise();
console.log(theNoise);
};
return instance;
};
var firstHorse = makeHorse();
var secondHorse = makeHorse();
secondHorse.setNeigh("mooo");
var firstWrapper = createSomething(firstHorse);
var secondWrapper = createSomething(secondHorse);
var nothingWrapper = createSomething();
firstWrapper.someMethod();
firstWrapper.callTheOther();
console.log(firstWrapper.doTheNoise());
secondWrapper.someMethod();
secondWrapper.callTheOther();
console.log(secondWrapper.doTheNoise());
nothingWrapper.someMethod();
//this call fails as we dont have this method on the fall through object (which is undefined)
console.log(nothingWrapper.doTheNoise());
This doesn't work for my use case as the extjs guys have not only mistakenly used 'this' they've also built a whole crazy classical inheritance type system on the principal of using prototypes and 'this'.
This is actually the first time I've used prototypes/constructors and I was slightly baffled that you can't just set the prototype - you also have to use a constructor. There is a magic field in objects (at least in firefox) call __proto which is basically the real prototype. it seems the actual prototype field is only used at construction time... how confusing!
Copying methods
This method is probably more expensive but seems more elegant to me and will also work on code that is using this (eg so you can use it to wrap library objects). It will also work on stuff written using the functional/closure style aswell - I've just illustrated it with this/constructors to show it works with stuff like that.
Here's the mods:
//this is now a constructor
var MakeHorse = function () {
this.neigh = "neigh";
};
MakeHorse.prototype.doTheNoise = function () {
return this.neigh + " is all im saying"
};
MakeHorse.prototype.setNeigh = function (newNoise) {
this.neigh = newNoise;
};
var createSomething = function (fallThrough) {
var instance = {
someMethod : function () {
console.log("aaaaa");
},
callTheOther : function () {
//note this has had to change to directly call the fallThrough object
var theNoise = fallThrough.doTheNoise();
console.log(theNoise);
}
};
//copy stuff over but not if it already exists
for (var propertyName in fallThrough)
if (!instance.hasOwnProperty(propertyName))
instance[propertyName] = fallThrough[propertyName];
return instance;
};
var firstHorse = new MakeHorse();
var secondHorse = new MakeHorse();
secondHorse.setNeigh("mooo");
var firstWrapper = createSomething(firstHorse);
var secondWrapper = createSomething(secondHorse);
var nothingWrapper = createSomething();
firstWrapper.someMethod();
firstWrapper.callTheOther();
console.log(firstWrapper.doTheNoise());
secondWrapper.someMethod();
secondWrapper.callTheOther();
console.log(secondWrapper.doTheNoise());
nothingWrapper.someMethod();
//this call fails as we dont have this method on the fall through object (which is undefined)
console.log(nothingWrapper.doTheNoise());
I was actually anticipating having to use bind in there somewhere but it appears not to be necessary.
Not to my knowledge, but you can simulate it by initializing the function to null at first and then replacing the implementation later.
var foo = null;
var bar = function() { alert(foo()); } // Appear to use foo before definition
// ...
foo = function() { return "ABC"; } /* Define the function */
bar(); /* Alert box pops up with "ABC" */
This trick is similar to a C# trick for implementing recursive lambdas, as described here.
The only downside is that if you do use foo before it's defined, you'll get an error for trying to call null as though it were a function, rather than a more descriptive error message. But you would expect to get some error message for using a function before it's defined.

Get name of prototype object

This question just got upvoted so can update question with what I did
I solved it by iterating over the window object (or user specified object root) and when I found the correct instance I backtracked and got the name from the index. The final solution can be found here
https://github.com/AndersMalmgren/Knockout.BindingConventions
Update end
I'm planning on writing a convention over configuration template source engine for KnockoutJS / MVC.
I'm started with a little client side POC and ran into a show stopper right away
My plan is use this syntax or something similar
MyApp.EditCustomersViewModel = function() {
ko.templates.loadView(this);
};
When doing this it will check the tamplate cache or fetch the templates from server using the object name as key.
The problem is I cant get the name of the prototype object, i tried this
Object.prototype.getName = function() {
var funcNameRegex = /function (.{1,})\(/;
var results = (funcNameRegex).exec((this).constructor.toString());
return (results && results.length > 1) ? results[1] : "";
};
If works for objects defined like this
function MyClass() {
}
If you add a prototype to the above object it will not work, or if you define it like this
MyApp = {};
MyApp.MyClass = function() {
};
Prototype and scoping is two musts so this is a showstopper, any ideas?
Fiddle: http://jsfiddle.net/aRWLA/
edit: The background for this is like this.
On the server you have structure like this
Templates\ [ViewName]\index.html
Templates\ [ViewName]\sub-model-template.html
on the client you will do
MyApp.EditCustomersViewModel = function() {
ko.templates.loadView(this);
};
which will generate a ajax request with the objects name as key, which will fetch all the templates for the view in question
Only hoisted functions (function someFunc() {) have a retrievable name.
Assigned functions do not, because you are not technically naming the function but creating an anonymous function and assigning a reference to it (in the memory) to a named variable.
So it's the var, not the function, that is named.
This makes the very idea of retrieving function names pretty much a none-starter, since in any vaguely mature pattern you'll be writing methods, not hoisted functions - and methods of course are assigned functions.
Named expressions (see other answers) are a partial workaround but these have other issues - not least lack of support in older IEs.
(Sidenote: I've long expected browser vendors to build around this such that the names of assigned functions became retrievable, but no joy yet AFAIK.)
I think you problem in improper replacing function prototype: if you replace function prototype object then you must preserve constructor member in prototype:
function Test1() {
}
Test1.prototype={
constructor: Test1
};
MyApp={};
MyApp.MyClass=function MyClass(){
};
MyApp.MyClass.prototype={
constructor: MyApp.MyClass
};
Your example: http://jsfiddle.net/aRWLA/1/
Modified example: http://jsfiddle.net/aRWLA/2/
You can make use of named function expressions:
MyApp.MyClass = function MyClass() { ... };
But note that (suprise) they don't work correctly in all versions of IE.
See: http://kangax.github.com/nfe/
THIS DOES NOT ANSWER THE QUESTION
However, the code might be useful to other people, so I'm leaving it here, just in case. I don't expect upvotes, but please don't abuse it for downvoting either. Thanks.
I don't know your use case, as such I think you've got a design issue - the problem you describe shouldn't happen in practice.
But let's say you do need to have this working. An easy way to do what you need would be something like:
function findNamed(obj, fn){
for(var p in obj)
if(obj[p] === fn)
return p;
return false;
}
var m = {};
m.MyClass = function() {};
console.log(findNamed(m, m.MyClass));
Of course, the solution could be made into a more appropriate OOP form, but this is just to give an idea.
To replicate your use case, it would look like:
m.MyClass = function() {
findNamed(this, arguments.callee);
};
So, the final code is:
Object.prototype.getNameOfCall = function(fn) {
for(var p in this)
if(this[p] === fn)
return p;
throw "Callback not in object.";
};
var m = {};
m.MyClass = function() {
console.log(this.getNameOfCall(arguments.callee)); // MyClass
};
m.MyClass(); // test it out

javascript - String to real Object

I have a javascript objects var flower_1; var flower_2;
My question is if I have another variable for example a String var Name;
And lets say for example: Name = "flower_1";
How can I change the Name variable into an object "flower_1"
If I understand your question correctly, you have something like this:
function foo() {
var flower_1 = { /* ... */ };
var flower_2 = { /* ... */ };
var name = "flower_1";
var target = /* code here to get the correct object based on `name` */;
}
You can do that, but it should be avoided if at all possible:
var target = eval(name);
eval is a very big, and easily abused tool which should be, and can be, avoided. I've never had to use it in production code in several years of JavaScript development. Also note that eval is disallowed in the new "strict" mode of the language (one of many improvements strict mode brings).
In this particular case, it's pretty easy to avoid:
function foo() {
var objects = {
flower_1: { /* ... */ },
flower_2: { /* ... */ }
};
var name = "flower_1";
var target = objects[name];
}
Now, flower_1 and flower_2 are properties of an object, and you can use bracketed notation ([]) with a string name to access those properties. This is because in JavaScript objects, you can either access a property using dotted notation and a literal (e.g., obj.foo), or using bracketed notation and a string (e.g., obj["foo"]). In the second case, the string doesn't have to be a string literal, it can be the result of an expression, including (as in this case) retrieving the string from a variable.
Here's a live example of both techniques.
Note that if your var statements are globals, then those vars become properties of the global object, which on web browsers is window, so if they're globals you could access them via window[name] for exactly the same reason objects[name] works. But it's best practice to avoid global variables (entirely if you can, or exposing just one with a good unique name that then contains all of your public stuff if necessary — e.g., if external code needs to access your stuff).
You can use the eval() function:
var flower_1 = "abc";
var name = "flower_1";
var x = eval(name); // = "abc"
It's worth noting though that use of the eval() function is not best practise, and should be avoided at all costs.
A better (and much more recommended) solution would be to use an associative array:
var name = "flower_1";
var arr = new Array();
arr["flower_1"] = "abc";
var x = arr[name]; // = "abc"

Categories