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!
Related
I have a Angular service and in it I have variables like this:
export class MyService {
someVariableA = 1;
someParams = {
someVariableB,
otherVariable: this.someVariableA
};
}
and in a component I set the 'someVariableA' to 3
this.myService.someVariableA = 3;
and I want 'otherVariable' to get that value 3 as well, but it doesn't. It remains 1 when I go to get the value.
let v = this.myService.someParams.otherVariable;
Is it possible to set 'otherVariable' this way or any other way via 'someVariableA'?
As #Zulwarnain answered, 1 is a number or a primitive data type. Primitive data types in javascript are passed by value, not by reference which you seem to be expecting here.
An easy fix for this is to assign a function to otherVariable instead. Now just invoke the function someParams.otherVariable() and it will return the value of someVariableA. No need to make this complicated.
export class SingletonService {
public someVariableA = 1;
public someParams = {
otherVariable: () => this.someVariableA
};
}
This is basic javascript with multiple sources covering the subject.
https://codeburst.io/explaining-value-vs-reference-in-javascript-647a975e12a0
I concur with this answer that you will have a better time if you use a reference type like an object/array instead of a primitive value type like a number. By adding one layer of indirection (e.g., someVar = 123 becomes someVar = {value: 123}) you could very easily get similar functionality to what you're seeking.
If, however, your use case requires an object's property to directly act like a reference to a primitive value type stored somewhere else, you can get this behavior by implementing the property as a getter and setter pair. It's more complicated, but it acts the way you want.
Here's an example:
class MyService {
someVariableA = 1;
someParams: {
someVariableB: number;
otherVariable: number;
};
constructor() {
this.someVariableA = 1;
const that = this;
this.someParams = {
someVariableB: 2,
get otherVariable() {
return that.someVariableA
},
set otherVariable(val: number) {
that.someVariableA = val;
}
}
}
}
Note that in order for the otherVariable getter and setter to be able to access the right context, I had to move the code into the constructor and copy this into a new variable I called that. The this context of a getter/setter refers to the object it's a member of, and not some this from an outer scope.
Let's make sure it works:
const ms = new MyService();
ms.someVariableA = 100;
console.log(ms.someParams.otherVariable); // 100
ms.someParams.otherVariable = -5;
console.log(ms.someVariableA); // -5
Looks good; changes to ms.someVariableA are immediately reflected in ms.someParams.otherVariable, and vice versa. All right, hope that helps; good luck!
Playground link to code
You are assigning the value type this will not work like you want. you need to assign reference type
obj ={someVariableA : 1};
someParams = {
otherVariable: this.obj
};
in the above code, if you change the value of obj.someVariableA it will also change the value of someParams.otherVariable
I am expexting that you have knowledge about reference type and value types variables
click here for demo
I don't think you want to do that. I believe you are getting a new instance of the service each time you call it, so the variables get reset.
you might want to set that variable in localStorage instead, and then have the service retrieve it from localStorage. That way it will always be getting whatever it was last set to.
or just pass that variable into your service call, instead of trying to use a local service variable.
I have a program that is incrementing requests on a session cookie and printing them out to the console. Initially, I was trying to figure out how I could save this data. After logging in a couple places, I realized that the data was being saved/changed despite me having a seperate variable to hold what I thought was a temporary version of the req member object.
This is the code that made me realize that the actual object was being changes when I incremented the variable I assigned it to:
recordRequest(req) {
const { ip } = req.info;
const { requestsPerSecond } = req.session;
if (req.originalUrl.split('/').filter(Boolean)[0] == 'www.example.com') {
requestsPerSecond[ip] = requestsPerSecond[ip] + 1 || 1;
}
console.log(req.session.requestsPerSecond);
}
I can't seem to find in the docs here or on Mozilla whether or not this is intended behavior, whether or not this is a result of my use of const (where you can mutate member variables), or there is some kind of weird bug going on. I also had trouble reproducing this example on a smaller scale, but I verified that nothing going in or going out of the function is affecting this chunk of code.
It's not breaking my code or anything (it's actually making my life easier) but I want to understand why this is happening!
I would default to object destructuring working essentially the same as normal assignments. Consider:
const req = {session: {requestsPerSecond: {"0.0.0.0": "foo"}}};
const requestsPerSecond = req.session.requestsPerSecond;
// updates to `requestsPerSecond` will also update `req`.
I'm not sure you can use destructuring to break the assignment, so you will have to use normal tactics:
const requestsPerSecond = Object.assign({}, req.session.requestsPerSecond);
From MDN:
The destructuring assignment syntax is a JavaScript expression that makes it possible to extract data from arrays or objects into distinct variables.
If this data happens to be an object reference, this object reference will be copied into the new variable, or in your case constant.
Minimal example:
const orig = {
foo: {
bar: 1
}
}
const { foo } = orig;
console.log(foo.bar); // 1
console.log(orig.foo.bar); // 1
foo.bar++;
console.log(foo.bar); // 2
console.log(orig.foo.bar); // 2
I want to create an object, starting from something like:
var map = {};
Then, I want to add items with this function:
add = function(integerA, objectB) {
map[objectB.type][integerA] = objectB;
}
So, this is a random example of the object structure I want to achieve:
map = {
'SomeType' : { 0 : 'obj', 2 : 'obj', 3 : 'obj' },
'OtherType' : { 0 : 'obj', 5 : 'obj' },
};
Now, my problem. I can't do map[objectB.type][integerA] = objectB; because map[objectB.type] is not defined. I could solve this by checking if map[objectB.type] exists through an if-statement and create map[objectB.type] = {}; when necessary.
Otherwise I could pre-load all object types. However I would prefer not to have to do this.
My question: is there a way I can create the object 'on the fly' without having to check if the type already exists every time I want to call the add function or to pre-load all the types?
It is important that my add function is so fast as possible and that the map object is correct, because I need to read and write a lot in a small amount of time (it's an animation / game application).
No, there is no any other way to create objects on the fly. Only check for existence every time:
add = function(integerA, objectB) {
if (!map[objectB.type]) {
map[objectB.type] = {};
}
map[objectB.type][integerA] = objectB;
}
If you want to improve performance you might consider some caching technics.
You can use the boolean OR shortcut (which avoids at least an explicit if). It might not be that readable though:
var data = map[objectB.type] || (map[objectB.type] = {});
data[integerA] = objectB;
This works because an assignment actually returns the value that was assigned and an OR expression returns the first value that evaluates to true.
I don't think using an if has any impact on the performance though (actually, the way in my answer might be even "slower").
If you use the map only for lookups and you don't need to iterate over the dimensions, you could merge your dimensions into a single key. For example:
add = function(integerA, objectB) {
var key = objectB.type + '-' + integerA;
map[key] = objectB;
}
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.
Weird problem here, I'm trying to use a global function to update my settings object, example:
var Settings = new Object;
Settings.savepos = 'true';
function UpdateSetting(obj,value){
eval("Settings.obj = value");
alert(Settings.savepos);
}
The obj is the key of the object, meaning if I call the function with
UpdateSetting('savepos','false')
the alert will always just give me true, how do I convert that eval or any alternative so it will update settings object's key with the value?
You are setting Settings.obj, not setting.savepos.
Try this instead:
function UpdateSetting(obj,value){
Settings[obj] = value;
alert(Settings.savepos);
};
You are always changing the "obj" key of the object to equal value, which is likely to be undefined (or, at least, not defined to what you want) in the context eval() executes it in. So, you have two options. First, you can keep using eval() (although i don't recommend it because it's more pain than necessary):
var Settings = new Object;
Settings.savepos = 'true';
function UpdateSetting(obj,value){
eval("Settings."+obj+" = '"+value+"'");
alert(Settings.savepos);
}
Or, as numerous other have suggested, you can use the array operator[] to access the property by key:
var Settings = new Object;
Settings.savepos = 'true';
function UpdateSetting(obj,value){
Settings[obj] = value;
alert(Settings.savepos);
}
you dont need an eval
you're setting .obj, not .savepos (there is no interpolation for the string)
you may be calling it wrong.
I'm not exactly sure why you don't just set the value directly (eg. Settings.savepos=false;).
You can attach the function to that object to do something similar:
var Settings = new Object;
Settings.savepos = true;
Settings.UpdateSetting = function (prop,value){this[prop] = value;}
Settings.UpdateSetting('savepos',false);
You should be able to use array notation on the object. Underneath it's just a keyed hash.
Try:
Settings[obj] = value;
I'd also suggest passing values as they are, i.e. string, int, etc:
UpdateSetting('key_name', false);