Javascript - how to declare namespace objects using new conventions - javascript

I am a big fan of latest programming conventions and latest additions to programming languages. Recently I read in Google Guidelines that we should use const and let instead of var.
Now in my project I have namespace object variables (if that's what they are called, correct me please if I am wrong) like this
var myObj = {
func1: {},
func2: {}
};
var myOtherObj = {
var1: 'foo',
var2: 'bar'
};
How should I name these objects now using the new conventions, with const or with let? I am confused because I don't know if these big objects change over time, or not...

const doesn't prevent objects from changing (said otherwise it doesn't freeze them). It prevents the value of variables to change.
For example you can still do
const myObj = {
func1: {},
func2: {}
};
and then
myObj.fun3 = function(){...
What you can't do with a variable declared with const (but which doesn't seem to be your will) is
myObj = {};
Modules are usually declared with const.

The general rule I try to follow is: const everywhere you can, let when you can't use const and var never.
In the case of your example, when you are defining objects (or in other cases arrays, etc.), I tend to define those with let to give a clear indication that either the variable reference could change or the contents inside.
const will not prevent properties of objects or elements in a list from being changed, so if you're unsure if thats going to happen, its best to use let in my opinion. It's more clear and could prevent confusion down the road.

If you really want a symbol that can't change value to refer to an object that is also immutable, you can do this:
const CONSTANT = Object.freeze({
a: "hello",
b: "world"
});
Also bear in mind that older platforms are still out there that won't support const and let (and probably Object.freeze() for that matter).

Related

Declare a const variable in javascript without initialization

In javascript, as per my understanding, we can declare variables with let and var keywords and assign it a value later.
var a;
a = 5;
But, when I try the same approach with const keyword it does not work.
const a;
Uncaught SyntaxError: Missing initializer in const declaration
I understand my question has a basic contradiction because const keywords are used for storing immutable variables. Therefore, a good coding practice may require it to be initialized while being declared.
However, I want to store global value in a const variable that is being fetched by an API. So, I was wondering if there is a way to assign a value to a pre-declared const variable in javascript?
const applies to the variable, not the value. You have to initialize them, because you can't assign them later -- that's the only difference they have. You can't have a variable that you can assign just once, but not reassign.
If the result is an object, you can declare the constant to hold an empty object, and then use Object.assign() to fill it in with the API response.
const result = {};
fetch(...).then(response => response.json()).then(data => Object.assign(result, data));
Have two ways to create a const with default value, 1 object with properties mutable, 2 array, as you can see bellow.
const a = {};
cosnt b = [];
I think you can not do that way . In JavaScript const variables must be assigned a value when they are declared:
Incorrect
const PI;
PI = 3.14159265359;
Correct
const PI = 3.14159265359;
For more reference you can take a look at this which gives you a better explanation
https://www.w3schools.com/js/js_const.asp
You can't do so, at least not in run-time. I suggest you consider using TypeScript, which has the readonly modifier which will help you protect your variable from being overwritten during compile-time.

Why Const is often used in object declaration while its properties could be changed? [duplicate]

This question already has answers here:
When to use const with objects in JavaScript?
(6 answers)
Closed 5 years ago.
my question is simple about Const. i have seen a lot places that devs prefer const over let and var while declaring object even its properties are mutable. Could somebody explain this?
const a = {};
a.name = "";
console.log(a.name);
Simply to prevent the object itself being overwritten or having its type changed. The constant will always be an object.
const a = {};
a = 'foo';
const b = {};
b = { foo: 'bar' };
Both will throw:
Uncaught TypeError: Assignment to constant variable.
It prevents a (in your example) from being assigned a different reference, but properties within the object are often needed to be changed as they convey the current state of the object instance.
A simply analogy, which is more correct here?
var me = "Scott";
const me = "Scott";
What should happen if this then happens?
me = you;
Let's forget the fact that, in real life, you can change you name if you really want to. In this case me should always and forever reference, well, me - "Scott" so const is the better declaration.
But, over my lifetime, characteristics of me will change, some that are out of my control and some that are in my control. So, while we don't want the me reference to change to reference a different object, aspects of the object that me does reference should be able to be changed:
const me = {};
me.height = "6' 1"; // Used to be 6' 3" back in the day!
But, if you needed a constant value to hold in an object, you could declare a private variable in a constructor function to do that.
function Me(height){
// Some aspects of this object will never change. They can be set up
// as private data:
const bloodType = "B+";
// Others are just properties:
this.height = height;
}
Or, you could continue to use an object literal, but you'd need to "lock down" certain properties so that become read-only. This is done with Object.defineProperty.
According to MDN
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. For instance, in the case where the content is an object, this means the object's contents (e.g., its parameters) can be altered.

JavaScript: Augmenting the Object/Function prototype avoiding name conflicts

Good day to everybody,
is there a method to augment the javascript Object and Function elements avoinding conflict issues? Let me be more specific:
Suppose i have 2 .js files :
ex1.js has Object.prototype.aMethod=function(){/*a function*/}
ex2.js has Object.prototype.aMethod=function(){/*another function*/}
In this situation, the ex1.js augmentation is overwritten by the one on ex2.js .
My question :
Is there a way to limit the effects of an augmentation to his file context, or better, to a module context?
EDIT:
Actually, i am reading crockford' s book JavaScript: the good parts, where he uses the prototype augmentation of Object and Function as something normal to do, without talking about the conflict issue. that' s strange, since the book leans to not pollute the global namespace. So i thought there must be some sort of workaround.
The prototype modifications are global if the Object you're modifying is global. To support what you're trying to do, you could use a module-local prototype:
var MyObject = function(properties) {
var key;
for(key in properties) {
if(properties.hasOwnProperty(key)) {
this[key] = properties[key];
}
}
};
MyObject.prototype.aMethod = function() {
console.log(this.name);
}
var obj = new MyObject({name: "blah"});
obj.aMethod();
// Prints "blah"
Modifying Object.prototype is usually considered "evil" on javascript, since the inherited properties show up on every for-in loop afterwards. Please note that modifying Object.prototype is different from modifying the Object object, which is what libraries such as Sugar.JS usually do.

Can global constants be declared in JavaScript?

If so, what is the syntax for such a declaration?
Javascript doesn't really have the notion of a named constant, or an immutable property of an object. (Note that I'm not talking about ES5 here.)
You can declare globals with a simple var declaration in the global scope, like outside any function in a script included by a web page:
<script>
var EXACTLY_ONE = 1;
Then your code can use that constant of course, though it's not really "constant" because the value can be changed (the property updated, in other words).
edit — this is an ancient answer to an ancient question. In 2019, there's the const declaration that's supported just about everywhere. However note that like let, const scoping is different from var scoping.
As "Pointy" so carefully notes, ECMAscript has no such feature. However, JavaScript does:
const a = 7;
document.writeln("a is " + a + ".");
Of course, if you're writing code to put on the web to run in web browsers, this might not help you much. :-)
Everything is global unless declared with the var keyword.
There are no constants either. You can simply declare them without the var keyword.
If you want to ensure global scope you can throw it into the window object:
window.GLOBAL_CONSTANT = "value";
You can do this from within any scope. Constants can then be declared inside functions or closures, though I wouldn't recommend that.
If you only care about supporting newer browsers (or are using a transpiler such as Babel to support older browsers) you can do the following:
Create a settings.js file with whatever constants you want and export them:
export const FRUIT = "kiwi";
export const VEGETABLE = "carrot";
In files that you want to use them you could then import them as follows:
import * as Settings from './settings.js'
Then to use the constants do something like this:
console.log("The unchangeable fruit is " + Settings.FRUIT);
This is a much cleaner approach than trying to implement a global constant, especially when you have multiple JavaScript files that you want to use the constants in.
You could do it with getters and setters like so:
Object.defineProperty(window, 'TAU', {
get: function(){return Math.PI*2;}
});
If you want a general function to do this:
function define(name, value){
Object.defineProperty(window, name, {
get: function(){return value;},
set: function(){throw(name+' is a constant and cannot be redeclared.');},
});
}
// Example use
define('TAU', Math.PI*2);
If you want to make sure the value cannot change use a function.
So, instead of:
var Const_X=12
use:
function Const_X() {
return 12;
}
The direct answer to the question is No. It would really help though if ECMA/JS made a way to easily do functional programming. A workable hack I use to get around this is to declare a const in the global scope and use a wrapper function see example below:
:)
global_var = 3; //This can change say inside a function etc. but once you decide to make
//this global variable into a constant by calling on a function
const make_variable_constant = function(variable)
{
const constant = variable;
return constant;
}
const const_global = make_variable_constant(global_var);
:)
Way back when object oriented programming was the hype a kid in my class told the C instructor that C isn't object oriented to which the instructor said he's done object oriented programming in C before Java and C++ were even conceived. Likewise you can do functional programming in Javascript but its much harder. Its like doing Object-oriented programming in C when its easier to do it in C++.
For the record.
// ES6+ code:
const CONSTGLOBAL1=200; // it is a constant global
function somef() {
document.write(CONSTGLOBAL1); // CONSTGLOBAL1 is defined (because it's global)
const CONSTLOCAL=200; // it's a local constant
document.write(CONSTLOCAL); // CONSTLOCAL is defined
}
somef();
document.write(CONSTLOCAL); // CONSTLOCALis NOT defined.
So, if the constant is defined inside {} then it's local, otherwise, it's global.
Similar to kojow7's answer, but instead of using grabbing all named exports I like to use one named export e.g. Constants and then declare my constants like this:
Create a Constants.js file with declaring your constants like this and export Constants:
// Constants.js
export const Constants = {
FRUIT: "kiwi",
VEGETABLE: "carrot",
};
Make a named import in the files you need a constant:
import { Constants } from './Constants';
Then use the constants as follows:
console.log("The unchangeable fruit is " + Constants.FRUIT);
There seems to be no downfall to use the one over the other option, but what I like personally is that I just name the file as I want to import it import { Constants } from './Constants'; and not always think about how I call it when grabbing all named exports import * as Constants from './Constants'. So in the second case I might want to look in another file where I imported already the constants and look how I named the import in case of consistency. Have a look also here for the different export/import possibilities.
If you're not planning to change the value of any object properties, you can use Object.freeze():
window.globalConst = Object.freeze( { x: 1, y: true } );
The following demonstrates the difference between const and Object.freeze():
const x = Object.freeze({
a: 1,
b: 2
});
x.a = 3;
// x.a is still = 1
console.log("x.a = ", x.a);
const y = {
a: 1,
b: 2
};
y.a = 3;
// y.a has been changed to 3
console.log("y.a = ", y.a);

Accessing variables from other functions without using global variables

I've heard from a variety of places that global variables are inherently nasty and evil, but when doing some non-object oriented Javascript, I can't see how to avoid them. Say I have a function which generates a number using a complex algorithm using random numbers and stuff, but I need to keep using that particular number in some other function which is a callback or something and so can't be part of the same function.
If the originally generated number is a local variable, it won't be accessible from, there. If the functions were object methods, I could make the number a property but they're not and it seems somewhat overcomplicated to change the whole program structure to do this. Is a global variable really so bad?
I think your best bet here may be to define a single global-scoped variable, and dumping your variables there:
var MyApp = {}; // Globally scoped object
function foo(){
MyApp.color = 'green';
}
function bar(){
alert(MyApp.color); // Alerts 'green'
}
No one should yell at you for doing something like the above.
To make a variable calculated in function A visible in function B, you have three choices:
make it a global,
make it an object property, or
pass it as a parameter when calling B from A.
If your program is fairly small then globals are not so bad. Otherwise I would consider using the third method:
function A()
{
var rand_num = calculate_random_number();
B(rand_num);
}
function B(r)
{
use_rand_num(r);
}
Consider using namespaces:
(function() {
var local_var = 'foo';
global_var = 'bar'; // this.global_var and window.global_var also work
function local_function() {}
global_function = function() {};
})();
Both local_function and global_function have access to all local and global variables.
Edit: Another common pattern:
var ns = (function() {
// local stuff
function foo() {}
function bar() {}
function baz() {} // this one stays invisible
// stuff visible in namespace object
return {
foo : foo,
bar : bar
};
})();
The returned properties can now be accessed via the namespace object, e.g. ns.foo, while still retaining access to local definitions.
What you're looking for is technically known as currying.
function getMyCallback(randomValue)
{
return function(otherParam)
{
return randomValue * otherParam //or whatever it is you are doing.
}
}
var myCallback = getMyCallBack(getRand())
alert(myCallBack(1));
alert(myCallBack(2));
The above isn't exactly a curried function but it achieves the result of maintaining an existing value without adding variables to the global namespace or requiring some other object repository for it.
I found this to be extremely helpful in relation to the original question:
Return the value you wish to use in functionOne, then call functionOne within functionTwo, then place the result into a fresh var and reference this new var within functionTwo. This should enable you to use the var declared in functionOne, within functionTwo.
function functionOne() {
var variableThree = 3;
return variableThree;
}
function functionTwo() {
var variableOne = 1;
var var3 = functionOne();
var result = var3 - variableOne;
console.log(variableOne);
console.log(var3);
console.log('functional result: ' + result);
}
functionTwo();
If another function needs to use a variable you pass it to the function as an argument.
Also global variables are not inherently nasty and evil. As long as they are used properly there is no problem with them.
If there's a chance that you will reuse this code, then I would probably make the effort to go with an object-oriented perspective. Using the global namespace can be dangerous -- you run the risk of hard to find bugs due to variable names that get reused. Typically I start by using an object-oriented approach for anything more than a simple callback so that I don't have to do the re-write thing. Any time that you have a group of related functions in javascript, I think, it's a candidate for an object-oriented approach.
Another approach is one that I picked up from a Douglas Crockford forum post(http://bytes.com/topic/javascript/answers/512361-array-objects). Here it is...
Douglas Crockford wrote:
Jul 15 '06
"If you want to retrieve objects by id, then you should use an object, not an
array. Since functions are also objects, you could store the members in the
function itself."
function objFacility(id, name, adr, city, state, zip) {
return objFacility[id] = {
id: id,
name: name,
adr: adr,
city: city,
state: state,
zip: zip
}
}
objFacility('wlevine', 'Levine', '23 Skid Row', 'Springfield', 'Il', 10010);
"The object can be obtained with"
objFacility.wlevine
The objects properties are now accessable from within any other function.
I don't know specifics of your issue, but if the function needs the value then it can be a parameter passed through the call.
Globals are considered bad because globals state and multiple modifiers can create hard to follow code and strange errors. To many actors fiddling with something can create chaos.
You can completely control the execution of javascript functions (and pass variables between them) using custom jQuery events....I was told that this wasn't possible all over these forums, but I got something working that does exactly that (even using an ajax call).
Here's the answer (IMPORTANT: it's not the checked answer but rather the answer by me "Emile"):
How to get a variable returned across multiple functions - Javascript/jQuery

Categories