Related
Is there a way to use constants in JavaScript?
If not, what's the common practice for specifying variables that are used as constants?
Since ES2015, JavaScript has a notion of const:
const MY_CONSTANT = "some-value";
This will work in pretty much all browsers except IE 8, 9 and 10. Some may also need strict mode enabled.
You can use var with conventions like ALL_CAPS to show that certain values should not be modified if you need to support older browsers or are working with legacy code:
var MY_CONSTANT = "some-value";
Are you trying to protect the variables against modification? If so, then you can use a module pattern:
var CONFIG = (function() {
var private = {
'MY_CONST': '1',
'ANOTHER_CONST': '2'
};
return {
get: function(name) { return private[name]; }
};
})();
alert('MY_CONST: ' + CONFIG.get('MY_CONST')); // 1
CONFIG.MY_CONST = '2';
alert('MY_CONST: ' + CONFIG.get('MY_CONST')); // 1
CONFIG.private.MY_CONST = '2'; // error
alert('MY_CONST: ' + CONFIG.get('MY_CONST')); // 1
Using this approach, the values cannot be modified. But, you have to use the get() method on CONFIG :(.
If you don't need to strictly protect the variables value, then just do as suggested and use a convention of ALL CAPS.
The const keyword is in the ECMAScript 6 draft but it thus far only enjoys a smattering of browser support: http://kangax.github.io/compat-table/es6/. The syntax is:
const CONSTANT_NAME = 0;
"use strict";
var constants = Object.freeze({
"π": 3.141592653589793 ,
"e": 2.718281828459045 ,
"i": Math.sqrt(-1)
});
constants.π; // -> 3.141592653589793
constants.π = 3; // -> TypeError: Cannot assign to read only property 'π' …
constants.π; // -> 3.141592653589793
delete constants.π; // -> TypeError: Unable to delete property.
constants.π; // -> 3.141592653589793
See Object.freeze. You can use const if you want to make the constants reference read-only as well.
IE does support constants, sort of, e.g.:
<script language="VBScript">
Const IE_CONST = True
</script>
<script type="text/javascript">
if (typeof TEST_CONST == 'undefined') {
const IE_CONST = false;
}
alert(IE_CONST);
</script>
ECMAScript 5 does introduce Object.defineProperty:
Object.defineProperty (window,'CONSTANT',{ value : 5, writable: false });
It's supported in every modern browser (as well as IE ≥ 9).
See also: Object.defineProperty in ES5?
No, not in general. Firefox implements const but I know IE doesn't.
#John points to a common naming practice for consts that has been used for years in other languages, I see no reason why you couldn't use that. Of course that doesn't mean someone will not write over the variable's value anyway. :)
In JavaScript, my preference is to use functions to return constant values.
function MY_CONSTANT() {
return "some-value";
}
alert(MY_CONSTANT());
Mozillas MDN Web Docs contain good examples and explanations about const. Excerpt:
// define MY_FAV as a constant and give it the value 7
const MY_FAV = 7;
// this will throw an error - Uncaught TypeError: Assignment to constant variable.
MY_FAV = 20;
But it is sad that IE9/10 still does not support const. And the reason it's absurd:
So, what is IE9 doing with const? So
far, our decision has been to not
support it. It isn’t yet a consensus
feature as it has never been available
on all browsers.
...
In the end, it seems like the best
long term solution for the web is to
leave it out and to wait for
standardization processes to run their
course.
They don't implement it because other browsers didn't implement it correctly?! Too afraid of making it better? Standards definitions or not, a constant is a constant: set once, never changed.
And to all the ideas: Every function can be overwritten (XSS etc.). So there is no difference in var or function(){return}. const is the only real constant.
Update:
IE11 supports const:
IE11 includes support for the well-defined and commonly used features of the emerging ECMAScript 6 standard including let, const, Map, Set, and WeakMap, as well as __proto__ for improved interoperability.
If you don't mind using functions:
var constant = function(val) {
return function() {
return val;
}
}
This approach gives you functions instead of regular variables, but it guarantees* that no one can alter the value once it's set.
a = constant(10);
a(); // 10
b = constant(20);
b(); // 20
I personally find this rather pleasant, specially after having gotten used to this pattern from knockout observables.
*Unless someone redefined the function constant before you called it
with the "new" Object api you can do something like this:
var obj = {};
Object.defineProperty(obj, 'CONSTANT', {
configurable: false
enumerable: true,
writable: false,
value: "your constant value"
});
take a look at this on the Mozilla MDN for more specifics. It's not a first level variable, as it is attached to an object, but if you have a scope, anything, you can attach it to that. this should work as well.
So for example doing this in the global scope will declare a pseudo constant value on the window (which is a really bad idea, you shouldn't declare global vars carelessly)
Object.defineProperty(this, 'constant', {
enumerable: true,
writable: false,
value: 7,
configurable: false
});
> constant
=> 7
> constant = 5
=> 7
note: assignment will give you back the assigned value in the console, but the variable's value will not change
Group constants into structures where possible:
Example, in my current game project, I have used below:
var CONST_WILD_TYPES = {
REGULAR: 'REGULAR',
EXPANDING: 'EXPANDING',
STICKY: 'STICKY',
SHIFTING: 'SHIFTING'
};
Assignment:
var wildType = CONST_WILD_TYPES.REGULAR;
Comparision:
if (wildType === CONST_WILD_TYPES.REGULAR) {
// do something here
}
More recently I am using, for comparision:
switch (wildType) {
case CONST_WILD_TYPES.REGULAR:
// do something here
break;
case CONST_WILD_TYPES.EXPANDING:
// do something here
break;
}
IE11 is with new ES6 standard that has 'const' declaration.
Above works in earlier browsers like IE8, IE9 & IE10.
Forget IE and use the const keyword.
You can easily equip your script with a mechanism for constants that can be set but not altered. An attempt to alter them will generate an error.
/* author Keith Evetts 2009 License: LGPL
anonymous function sets up:
global function SETCONST (String name, mixed value)
global function CONST (String name)
constants once set may not be altered - console error is generated
they are retrieved as CONST(name)
the object holding the constants is private and cannot be accessed from the outer script directly, only through the setter and getter provided
*/
(function(){
var constants = {};
self.SETCONST = function(name,value) {
if (typeof name !== 'string') { throw new Error('constant name is not a string'); }
if (!value) { throw new Error(' no value supplied for constant ' + name); }
else if ((name in constants) ) { throw new Error('constant ' + name + ' is already defined'); }
else {
constants[name] = value;
return true;
}
};
self.CONST = function(name) {
if (typeof name !== 'string') { throw new Error('constant name is not a string'); }
if ( name in constants ) { return constants[name]; }
else { throw new Error('constant ' + name + ' has not been defined'); }
};
}())
// ------------- demo ----------------------------
SETCONST( 'VAT', 0.175 );
alert( CONST('VAT') );
//try to alter the value of VAT
try{
SETCONST( 'VAT', 0.22 );
} catch ( exc ) {
alert (exc.message);
}
//check old value of VAT remains
alert( CONST('VAT') );
// try to get at constants object directly
constants['DODO'] = "dead bird"; // error
Yet there is no exact cross browser predefined way to do it , you can achieve it by controlling the scope of variables as showed on other answers.
But i will suggest to use name space to distinguish from other variables. this will reduce the chance of collision to minimum from other variables.
Proper namespacing like
var iw_constant={
name:'sudhanshu',
age:'23'
//all varibale come like this
}
so while using it will be iw_constant.name or iw_constant.age
You can also block adding any new key or changing any key inside iw_constant using Object.freeze method. However its not supported on legacy browser.
ex:
Object.freeze(iw_constant);
For older browser you can use polyfill for freeze method.
If you are ok with calling function following is best cross browser way to define constant. Scoping your object within a self executing function and returning a get function for your constants
ex:
var iw_constant= (function(){
var allConstant={
name:'sudhanshu',
age:'23'
//all varibale come like this
};
return function(key){
allConstant[key];
}
};
//to get the value use
iw_constant('name') or iw_constant('age')
** In both example you have to be very careful on name spacing so that your object or function shouldn't be replaced through other library.(If object or function itself wil be replaced your whole constant will go)
For a while, I specified "constants" (which still weren't actually constants) in object literals passed through to with() statements. I thought it was so clever. Here's an example:
with ({
MY_CONST : 'some really important value'
}) {
alert(MY_CONST);
}
In the past, I also have created a CONST namespace where I would put all of my constants. Again, with the overhead. Sheesh.
Now, I just do var MY_CONST = 'whatever'; to KISS.
My opinion (works only with objects).
var constants = (function(){
var a = 9;
//GLOBAL CONSTANT (through "return")
window.__defineGetter__("GCONST", function(){
return a;
});
//LOCAL CONSTANT
return {
get CONST(){
return a;
}
}
})();
constants.CONST = 8; //9
alert(constants.CONST); //9
Try! But understand - this is object, but not simple variable.
Try also just:
const a = 9;
I too have had a problem with this. And after quite a while searching for the answer and looking at all the responses by everybody, I think I've come up with a viable solution to this.
It seems that most of the answers that I've come across is using functions to hold the constants. As many of the users of the MANY forums post about, the functions can be easily over written by users on the client side. I was intrigued by Keith Evetts' answer that the constants object can not be accessed by the outside, but only from the functions on the inside.
So I came up with this solution:
Put everything inside an anonymous function so that way, the variables, objects, etc. cannot be changed by the client side. Also hide the 'real' functions by having other functions call the 'real' functions from the inside. I also thought of using functions to check if a function has been changed by a user on the client side. If the functions have been changed, change them back using variables that are 'protected' on the inside and cannot be changed.
/*Tested in: IE 9.0.8; Firefox 14.0.1; Chrome 20.0.1180.60 m; Not Tested in Safari*/
(function(){
/*The two functions _define and _access are from Keith Evetts 2009 License: LGPL (SETCONST and CONST).
They're the same just as he did them, the only things I changed are the variable names and the text
of the error messages.
*/
//object literal to hold the constants
var j = {};
/*Global function _define(String h, mixed m). I named it define to mimic the way PHP 'defines' constants.
The argument 'h' is the name of the const and has to be a string, 'm' is the value of the const and has
to exist. If there is already a property with the same name in the object holder, then we throw an error.
If not, we add the property and set the value to it. This is a 'hidden' function and the user doesn't
see any of your coding call this function. You call the _makeDef() in your code and that function calls
this function. - You can change the error messages to whatever you want them to say.
*/
self._define = function(h,m) {
if (typeof h !== 'string') { throw new Error('I don\'t know what to do.'); }
if (!m) { throw new Error('I don\'t know what to do.'); }
else if ((h in j) ) { throw new Error('We have a problem!'); }
else {
j[h] = m;
return true;
}
};
/*Global function _makeDef(String t, mixed y). I named it makeDef because we 'make the define' with this
function. The argument 't' is the name of the const and doesn't need to be all caps because I set it
to upper case within the function, 'y' is the value of the value of the const and has to exist. I
make different variables to make it harder for a user to figure out whats going on. We then call the
_define function with the two new variables. You call this function in your code to set the constant.
You can change the error message to whatever you want it to say.
*/
self._makeDef = function(t, y) {
if(!y) { throw new Error('I don\'t know what to do.'); return false; }
q = t.toUpperCase();
w = y;
_define(q, w);
};
/*Global function _getDef(String s). I named it getDef because we 'get the define' with this function. The
argument 's' is the name of the const and doesn't need to be all capse because I set it to upper case
within the function. I make a different variable to make it harder for a user to figure out whats going
on. The function returns the _access function call. I pass the new variable and the original string
along to the _access function. I do this because if a user is trying to get the value of something, if
there is an error the argument doesn't get displayed with upper case in the error message. You call this
function in your code to get the constant.
*/
self._getDef = function(s) {
z = s.toUpperCase();
return _access(z, s);
};
/*Global function _access(String g, String f). I named it access because we 'access' the constant through
this function. The argument 'g' is the name of the const and its all upper case, 'f' is also the name
of the const, but its the original string that was passed to the _getDef() function. If there is an
error, the original string, 'f', is displayed. This makes it harder for a user to figure out how the
constants are being stored. If there is a property with the same name in the object holder, we return
the constant value. If not, we check if the 'f' variable exists, if not, set it to the value of 'g' and
throw an error. This is a 'hidden' function and the user doesn't see any of your coding call this
function. You call the _getDef() function in your code and that function calls this function.
You can change the error messages to whatever you want them to say.
*/
self._access = function(g, f) {
if (typeof g !== 'string') { throw new Error('I don\'t know what to do.'); }
if ( g in j ) { return j[g]; }
else { if(!f) { f = g; } throw new Error('I don\'t know what to do. I have no idea what \''+f+'\' is.'); }
};
/*The four variables below are private and cannot be accessed from the outside script except for the
functions inside this anonymous function. These variables are strings of the four above functions and
will be used by the all-dreaded eval() function to set them back to their original if any of them should
be changed by a user trying to hack your code.
*/
var _define_func_string = "function(h,m) {"+" if (typeof h !== 'string') { throw new Error('I don\\'t know what to do.'); }"+" if (!m) { throw new Error('I don\\'t know what to do.'); }"+" else if ((h in j) ) { throw new Error('We have a problem!'); }"+" else {"+" j[h] = m;"+" return true;"+" }"+" }";
var _makeDef_func_string = "function(t, y) {"+" if(!y) { throw new Error('I don\\'t know what to do.'); return false; }"+" q = t.toUpperCase();"+" w = y;"+" _define(q, w);"+" }";
var _getDef_func_string = "function(s) {"+" z = s.toUpperCase();"+" return _access(z, s);"+" }";
var _access_func_string = "function(g, f) {"+" if (typeof g !== 'string') { throw new Error('I don\\'t know what to do.'); }"+" if ( g in j ) { return j[g]; }"+" else { if(!f) { f = g; } throw new Error('I don\\'t know what to do. I have no idea what \\''+f+'\\' is.'); }"+" }";
/*Global function _doFunctionCheck(String u). I named it doFunctionCheck because we're 'checking the functions'
The argument 'u' is the name of any of the four above function names you want to check. This function will
check if a specific line of code is inside a given function. If it is, then we do nothing, if not, then
we use the eval() function to set the function back to its original coding using the function string
variables above. This function will also throw an error depending upon the doError variable being set to true
This is a 'hidden' function and the user doesn't see any of your coding call this function. You call the
doCodeCheck() function and that function calls this function. - You can change the error messages to
whatever you want them to say.
*/
self._doFunctionCheck = function(u) {
var errMsg = 'We have a BIG problem! You\'ve changed my code.';
var doError = true;
d = u;
switch(d.toLowerCase())
{
case "_getdef":
if(_getDef.toString().indexOf("z = s.toUpperCase();") != -1) { /*do nothing*/ }
else { eval("_getDef = "+_getDef_func_string); if(doError === true) { throw new Error(errMsg); } }
break;
case "_makedef":
if(_makeDef.toString().indexOf("q = t.toUpperCase();") != -1) { /*do nothing*/ }
else { eval("_makeDef = "+_makeDef_func_string); if(doError === true) { throw new Error(errMsg); } }
break;
case "_define":
if(_define.toString().indexOf("else if((h in j) ) {") != -1) { /*do nothing*/ }
else { eval("_define = "+_define_func_string); if(doError === true) { throw new Error(errMsg); } }
break;
case "_access":
if(_access.toString().indexOf("else { if(!f) { f = g; }") != -1) { /*do nothing*/ }
else { eval("_access = "+_access_func_string); if(doError === true) { throw new Error(errMsg); } }
break;
default:
if(doError === true) { throw new Error('I don\'t know what to do.'); }
}
};
/*Global function _doCodeCheck(String v). I named it doCodeCheck because we're 'doing a code check'. The argument
'v' is the name of one of the first four functions in this script that you want to check. I make a different
variable to make it harder for a user to figure out whats going on. You call this function in your code to check
if any of the functions has been changed by the user.
*/
self._doCodeCheck = function(v) {
l = v;
_doFunctionCheck(l);
};
}())
It also seems that security is really a problem and there is not way to 'hide' you programming from the client side. A good idea for me is to compress your code so that it is really hard for anyone, including you, the programmer, to read and understand it. There is a site you can go to: http://javascriptcompressor.com/. (This is not my site, don't worry I'm not advertising.) This is a site that will let you compress and obfuscate Javascript code for free.
Copy all the code in the above script and paste it into the top textarea on the javascriptcompressor.com page.
Check the Base62 encode checkbox, check the Shrink Variables checkbox.
Press the Compress button.
Paste and save it all in a .js file and add it to your page in the head of your page.
Clearly this shows the need for a standardized cross-browser const keyword.
But for now:
var myconst = value;
or
Object['myconst'] = value;
Both seem sufficient and anything else is like shooting a fly with a bazooka.
I use const instead of var in my Greasemonkey scripts, but it is because they will run only on Firefox...
Name convention can be indeed the way to go, too (I do both!).
In JavaScript my practice has been to avoid constants as much as I can and use strings instead. Problems with constants appear when you want to expose your constants to the outside world:
For example one could implement the following Date API:
date.add(5, MyModule.Date.DAY).add(12, MyModule.Date.HOUR)
But it's much shorter and more natural to simply write:
date.add(5, "days").add(12, "hours")
This way "days" and "hours" really act like constants, because you can't change from the outside how many seconds "hours" represents. But it's easy to overwrite MyModule.Date.HOUR.
This kind of approach will also aid in debugging. If Firebug tells you action === 18 it's pretty hard to figure out what it means, but when you see action === "save" then it's immediately clear.
Okay, this is ugly, but it gives me a constant in Firefox and Chromium, an inconstant constant (WTF?) in Safari and Opera, and a variable in IE.
Of course eval() is evil, but without it, IE throws an error, preventing scripts from running.
Safari and Opera support the const keyword, but you can change the const's value.
In this example, server-side code is writing JavaScript to the page, replacing {0} with a value.
try{
// i can haz const?
eval("const FOO='{0}';");
// for reals?
var original=FOO;
try{
FOO='?NO!';
}catch(err1){
// no err from Firefox/Chrome - fails silently
alert('err1 '+err1);
}
alert('const '+FOO);
if(FOO=='?NO!'){
// changed in Sf/Op - set back to original value
FOO=original;
}
}catch(err2){
// IE fail
alert('err2 '+err2);
// set var (no var keyword - Chrome/Firefox complain about redefining const)
FOO='{0}';
alert('var '+FOO);
}
alert('FOO '+FOO);
What is this good for? Not much, since it's not cross-browser. At best, maybe a little peace of mind that at least some browsers won't let bookmarklets or third-party script modify the value.
Tested with Firefox 2, 3, 3.6, 4, Iron 8, Chrome 10, 12, Opera 11, Safari 5, IE 6, 9.
If it is worth mentioning, you can define constants in angular using $provide.constant()
angularApp.constant('YOUR_CONSTANT', 'value');
An improved version of Burke's answer that lets you do CONFIG.MY_CONST instead of CONFIG.get('MY_CONST').
It requires IE9+ or a real web browser.
var CONFIG = (function() {
var constants = {
'MY_CONST': 1,
'ANOTHER_CONST': 2
};
var result = {};
for (var n in constants)
if (constants.hasOwnProperty(n))
Object.defineProperty(result, n, { value: constants[n] });
return result;
}());
* The properties are read-only, only if the initial values are immutable.
JavaScript ES6 (re-)introduced the const keyword which is supported in all major browsers.
Variables declared via const cannot be re-declared or re-assigned.
Apart from that, const behaves similar to let.
It behaves as expected for primitive datatypes (Boolean, Null, Undefined, Number, String, Symbol):
const x = 1;
x = 2;
console.log(x); // 1 ...as expected, re-assigning fails
Attention: Be aware of the pitfalls regarding objects:
const o = {x: 1};
o = {x: 2};
console.log(o); // {x: 1} ...as expected, re-assigning fails
o.x = 2;
console.log(o); // {x: 2} !!! const does not make objects immutable!
const a = [];
a = [1];
console.log(a); // 1 ...as expected, re-assigning fails
a.push(1);
console.log(a); // [1] !!! const does not make objects immutable
If you really need an immutable and absolutely constant object: Just use const ALL_CAPS to make your intention clear. It is a good convention to follow for all const declarations anyway, so just rely on it.
Another alternative is something like:
var constants = {
MY_CONSTANT : "myconstant",
SOMETHING_ELSE : 123
}
, constantMap = new function ConstantMap() {};
for(var c in constants) {
!function(cKey) {
Object.defineProperty(constantMap, cKey, {
enumerable : true,
get : function(name) { return constants[cKey]; }
})
}(c);
}
Then simply: var foo = constantMap.MY_CONSTANT
If you were to constantMap.MY_CONSTANT = "bar" it would have no effect as we're trying to use an assignment operator with a getter, hence constantMap.MY_CONSTANT === "myconstant" would remain true.
in Javascript already exists constants. You define a constant like this:
const name1 = value;
This cannot change through reassignment.
The keyword 'const' was proposed earlier and now it has been officially included in ES6. By using the const keyword, you can pass a value/string that will act as an immutable string.
Introducing constants into JavaScript is at best a hack.
A nice way of making persistent and globally accessible values in JavaScript would be declaring an object literal with some "read-only" properties like this:
my={get constant1(){return "constant 1"},
get constant2(){return "constant 2"},
get constant3(){return "constant 3"},
get constantN(){return "constant N"}
}
you'll have all your constants grouped in one single "my" accessory object where you can look for your stored values or anything else you may have decided to put there for that matter. Now let's test if it works:
my.constant1; >> "constant 1"
my.constant1 = "new constant 1";
my.constant1; >> "constant 1"
As we can see, the "my.constant1" property has preserved its original value. You've made yourself some nice 'green' temporary constants...
But of course this will only guard you from accidentally modifying, altering, nullifying, or emptying your property constant value with a direct access as in the given example.
Otherwise I still think that constants are for dummies.
And I still think that exchanging your great freedom for a small corner of deceptive security is the worst trade possible.
Rhino.js implements const in addition to what was mentioned above.
I want to build a table in Raect with a sorted list of watches of a certain ebay listing.I figured out that the problem is this line:
entriesObj[value][1][0].listingInfo[0].watchCount[0]
because sometimes listing don't have any watches at all and in this case value watchCount doesn't exist at all so I can't loop through it, although I tried to use conditional operator (and if else statements in many different ways) it still throws an error. First I created an object:
watcherCount = () => {
return (
this.state.itemList.reduce((watcherObject,item) => {
const watcherKey = item.itemId;
if (!watcherObject[watcherKey]) {
watcherObject[watcherKey] = [item];
} else {
watcherObject[watcherKey].push(item);
}
return watcherObject;
},{})
);
}
and now I am trying to move them to an array ([number of watches, title of listing, item id]) in order to sort them:
import React from 'react';
class Watches extends React.Component {
render () {
var entriesObj = Object.entries(this.props.watcherCount);
var sortable = [];
for (var value in entriesObj){
for (var value in entriesObj){
sortable.push([typeof entriesObj[value][1][0].listingInfo[0].watchCount[0] === "undefined" ? "-" : entriesObj[value][1][0].listingInfo[0].watchCount[0], entriesObj[value][1][0].title[0], entriesObj[value][0]]);
}
}
sortable.sort(function(a, b) {
return b[0] - a[0];
});
console.log(sortable);
//Output: Uncaught (in promise) TypeError: Cannot read property '0' of undefined
return <table></table>
}
}
export default Watches;
Do you know any other way to build this exact kind of array or how to solve the problem with missing property?
I Don't know if I fully understood the problem.
In cases with deep references, if I don't want or can't use any conditional checks I simply put the object path reference in a try catch (finally) block.
e.g. (untested though)
for (var value in entriesObj){
var val;
try {
// just make sure the only error that might be occuring
// here is an object reference error
// therefore the array push happens after the try catch block
val = entriesObj[value][1][0].listingInfo[0].watchCount[0], entriesObj[value][1][0].title[0], entriesObj[value][0]];
} catch(err) {
val = "-";
// log the error or maybe issue a warning since missing items
// is actually expected behaviour
} finally {
sortable.push(val);
}
}
Maybe it solves your problem.
I am emiting object with socket.io
socket.emit('object',{"object":collection});
but it happens sometimes when socket.io cant emit object right now because cant reach server, socket.io remembers that emit in memory, but collection changes in meantime and on server we recieve empty object.
I tried also
socket.emit('object',function(collection){
return {"object":collection};
}(collection)
but it goes with same empty object (in the meanwhile collection is empty.
Objects in JavaScript are passed by reference. Any changes outside an asynchronous function to such an object are reflected later on in the object itself.
A simple solution is to copy the object by creating a new one which has all properties (and maybe methods...) of the original.
Example for arrays would be this neat little code: [].concat(collection);. But since we're talking objects here, that won't work. With jQuery, this would be as easy as $.extend({}, collection);, but since you didn't tag it, let's make our own version of that method.
function extend( to, from, deep ) {
// Double negation to force deep to be a boolean even if not provided. Thus: defaults to false.
deep = !!deep;
for( var i in from ) {
if( deep ) {
if( typeof from[i] == 'object' ) {
// Array?
if( from[i].length && typeof from[i].splice == 'function' ) {
to[i] = [].concat(from[i]);
}
// nested object!
else {
to[i] = {};
extend(to[i], from[i], deep);
}
}
else {
to[i] = from[i];
}
}
}
return to;
}
Applying it to socket.emit:
socket.emit('object', {
'object' : extend({}, collection, true)
});
Note that circular references will result in an infinite loop when deep copying.
I am working on a program in node.js which is actually js.
I have a variable :
var query = azure.TableQuery...
looks this line of the code is not executing some times.
my question is :
How can I do a condition like:
if this variable is defined do this.
else do this.
I cannot do in js (query!= null)
I want to see if this variable is defined do some thing. how to do this
if ( typeof query !== 'undefined' && query )
{
//do stuff if query is defined and not null
}
else
{
}
Determine if property is existing (but is not a falsy value):
if (typeof query !== 'undefined' && query !== null){
doStuff();
}
Usually using
if (query){
doStuff();
}
is sufficient. Please note that:
if (!query){
doStuff();
}
doStuff() will execute even if query was an existing variable with falsy value (0, false, undefined or null)
Btw, there's a sexy coffeescript way of doing this:
if object?.property? then doStuff()
which compiles to:
if ((typeof object !== "undefined" && object !== null ? object.property : void 0) != null)
{
doStuff();
}
For me, an expression like
if (typeof query !== 'undefined' && query !== null){
// do stuff
}
is more complicated than I want for how often I want to use it. That is, testing if a variable is defined/null is something I do frequently. I want such a test to be simple. To resolve this, I first tried to define the above code as a function, but node just gives me a syntax error, telling me the parameter to the function call is undefined. Not useful! So, searching about and working on this bit, I found a solution. Not for everyone perhaps. My solution involves using Sweet.js to define a macro. Here's how I did it:
Here's the macro (filename: macro.sjs):
// I had to install sweet using:
// npm install --save-dev
// See: https://www.npmjs.com/package/sweetbuild
// Followed instructions from https://github.com/mozilla/sweet.js/wiki/node-loader
// Initially I just had "($x)" in the macro below. But this failed to match with
// expressions such as "self.x. Adding the :expr qualifier cures things. See
// http://jlongster.com/Writing-Your-First-Sweet.js-Macro
macro isDefined {
rule {
($x:expr)
} => {
(( typeof ($x) === 'undefined' || ($x) === null) ? false : true)
}
}
// Seems the macros have to be exported
// https://github.com/mozilla/sweet.js/wiki/modules
export isDefined;
Here's an example of usage of the macro (in example.sjs):
function Foobar() {
var self = this;
self.x = 10;
console.log(isDefined(y)); // false
console.log(isDefined(self.x)); // true
}
module.exports = Foobar;
And here's the main node file:
var sweet = require('sweet.js');
// load all exported macros in `macros.sjs`
sweet.loadMacro('./macro.sjs');
// example.sjs uses macros that have been defined and exported in `macros.sjs`
var Foobar = require('./example.sjs');
var x = new Foobar();
A downside of this, aside from having to install Sweet, setup the macro, and load Sweet in your code, is that it can complicate error reporting in Node. It adds a second layer of parsing. Haven't worked with this much yet, so shall see how it goes first hand. I like Sweet though and I miss macros so will try to stick with it!
If your variable is not declared nor defined:
if ( typeof query !== 'undefined' ) { ... }
If your variable is declared but undefined. (assuming the case here is that the variable might not be defined but it can be any other falsy value like false or "")
if ( query ) { ... }
If your variable is declared but can be undefined or null:
if ( query != null ) { ... } // undefined == null
For easy tasks I often simply do it like:
var undef;
// Fails on undefined variables
if (query !== undef) {
// variable is defined
} else {
// else do this
}
Or if you simply want to check for a nulled value too..
var undef;
// Fails on undefined variables
// And even fails on null values
if (query != undef) {
// variable is defined and not null
} else {
// else do this
}
It sounds like you're doing property checking on an object! If you want to check a property exists (but can be values such as null or 0 in addition to truthy values), the in operator can make for some nice syntax.
var foo = { bar: 1234, baz: null };
console.log("bar in foo:", "bar" in foo); // true
console.log("baz in foo:", "baz" in foo); // true
console.log("otherProp in foo:", "otherProp" in foo) // false
console.log("__proto__ in foo:", "__proto__" in foo) // true
As you can see, the __proto__ property is going to be thrown here. This is true for all inherited properties. For further reading, I'd recommend the MDN page:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in
You could use double exclamation mark !! to check if something is defined and not null.
!!null returns false.
!!undefined will also return false.
But if you define a variable for example const a = 1, then !!a will return true.
I have seen a lot of options here, but I would say, that in some cases the code will execute not the way expected, or throw an error. If you want a safe way, use try catch:
try {
I_dont_exist
} catch (err) {
console.log('Variable is not defined')
}
I'm learning how to make OOP with JavaScript. Does it have the interface concept (such as Java's interface)?
So I would be able to create a listener...
There's no notion of "this class must have these functions" (that is, no interfaces per se), because:
JavaScript inheritance is based on objects, not classes. That's not a big deal until you realize:
JavaScript is an extremely dynamically typed language -- you can create an object with the proper methods, which would make it conform to the interface, and then undefine all the stuff that made it conform. It'd be so easy to subvert the type system -- even accidentally! -- that it wouldn't be worth it to try and make a type system in the first place.
Instead, JavaScript uses what's called duck typing. (If it walks like a duck, and quacks like a duck, as far as JS cares, it's a duck.) If your object has quack(), walk(), and fly() methods, code can use it wherever it expects an object that can walk, quack, and fly, without requiring the implementation of some "Duckable" interface. The interface is exactly the set of functions that the code uses (and the return values from those functions), and with duck typing, you get that for free.
Now, that's not to say your code won't fail halfway through, if you try to call some_dog.quack(); you'll get a TypeError. Frankly, if you're telling dogs to quack, you have slightly bigger problems; duck typing works best when you keep all your ducks in a row, so to speak, and aren't letting dogs and ducks mingle together unless you're treating them as generic animals. In other words, even though the interface is fluid, it's still there; it's often an error to pass a dog to code that expects it to quack and fly in the first place.
But if you're sure you're doing the right thing, you can work around the quacking-dog problem by testing for the existence of a particular method before trying to use it. Something like
if (typeof(someObject.quack) == "function")
{
// This thing can quack
}
So you can check for all the methods you can use before you use them. The syntax is kind of ugly, though. There's a slightly prettier way:
Object.prototype.can = function(methodName)
{
return ((typeof this[methodName]) == "function");
};
if (someObject.can("quack"))
{
someObject.quack();
}
This is standard JavaScript, so it should work in any JS interpreter worth using. It has the added benefit of reading like English.
For modern browsers (that is, pretty much any browser other than IE 6-8), there's even a way to keep the property from showing up in for...in:
Object.defineProperty(Object.prototype, 'can', {
enumerable: false,
value: function(method) {
return (typeof this[method] === 'function');
}
}
The problem is that IE7 objects don't have .defineProperty at all, and in IE8, it allegedly only works on host objects (that is, DOM elements and such). If compatibility is an issue, you can't use .defineProperty. (I won't even mention IE6, because it's rather irrelevant anymore outside of China.)
Another issue is that some coding styles like to assume that everyone writes bad code, and prohibit modifying Object.prototype in case someone wants to blindly use for...in. If you care about that, or are using (IMO broken) code that does, try a slightly different version:
function can(obj, methodName)
{
return ((typeof obj[methodName]) == "function");
}
if (can(someObject, "quack"))
{
someObject.quack();
}
Pick up a copy of 'JavaScript design patterns' by Dustin Diaz. There's a few chapters dedicated to implementing JavaScript interfaces through Duck Typing. It's a nice read as well. But no, there's no language native implementation of an interface, you have to Duck Type.
// example duck typing method
var hasMethods = function(obj /*, method list as strings */){
var i = 1, methodName;
while((methodName = arguments[i++])){
if(typeof obj[methodName] != 'function') {
return false;
}
}
return true;
}
// in your code
if(hasMethods(obj, 'quak', 'flapWings','waggle')) {
// IT'S A DUCK, do your duck thang
}
JavaScript (ECMAScript edition 3) has an implements reserved word saved up for future use. I think this is intended exactly for this purpose, however, in a rush to get the specification out the door they didn't have time to define what to do with it, so, at the present time, browsers don't do anything besides let it sit there and occasionally complain if you try to use it for something.
It is possible and indeed easy enough to create your own Object.implement(Interface) method with logic that baulks whenever a particular set of properties/functions are not implemented in a given object.
I wrote an article on object-orientation where use my own notation as follows:
// Create a 'Dog' class that inherits from 'Animal'
// and implements the 'Mammal' interface
var Dog = Object.extend(Animal, {
constructor: function(name) {
Dog.superClass.call(this, name);
},
bark: function() {
alert('woof');
}
}).implement(Mammal);
There are many ways to skin this particular cat, but this is the logic I used for my own Interface implementation. I find I prefer this approach, and it is easy to read and use (as you can see above). It does mean adding an 'implement' method to Function.prototype which some people may have a problem with, but I find it works beautifully.
Function.prototype.implement = function() {
// Loop through each interface passed in and then check
// that its members are implemented in the context object (this).
for(var i = 0; i < arguments.length; i++) {
// .. Check member's logic ..
}
// Remember to return the class being tested
return this;
}
JavaScript Interfaces:
Though JavaScript does not have the interface type, it is often times needed. For reasons relating to JavaScript's dynamic nature and use of Prototypical-Inheritance, it is difficult to ensure consistent interfaces across classes -- however, it is possible to do so; and frequently emulated.
At this point, there are handfuls of particular ways to emulate Interfaces in JavaScript; variance on approaches usually satisfies some needs, while others are left unaddressed. Often times, the most robust approach is overly cumbersome and stymies the implementor (developer).
Here is an approach to Interfaces / Abstract Classes that is not very cumbersome, is explicative, keeps implementations inside of Abstractions to a minimum, and leaves enough room for dynamic or custom methodologies:
function resolvePrecept(interfaceName) {
var interfaceName = interfaceName;
return function curry(value) {
/* throw new Error(interfaceName + ' requires an implementation for ...'); */
console.warn('%s requires an implementation for ...', interfaceName);
return value;
};
}
var iAbstractClass = function AbstractClass() {
var defaultTo = resolvePrecept('iAbstractClass');
this.datum1 = this.datum1 || defaultTo(new Number());
this.datum2 = this.datum2 || defaultTo(new String());
this.method1 = this.method1 || defaultTo(new Function('return new Boolean();'));
this.method2 = this.method2 || defaultTo(new Function('return new Object();'));
};
var ConcreteImplementation = function ConcreteImplementation() {
this.datum1 = 1;
this.datum2 = 'str';
this.method1 = function method1() {
return true;
};
this.method2 = function method2() {
return {};
};
//Applies Interface (Implement iAbstractClass Interface)
iAbstractClass.apply(this); // .call / .apply after precept definitions
};
Participants
Precept Resolver
The resolvePrecept function is a utility & helper function to use inside of your Abstract Class. Its job is to allow for customized implementation-handling of encapsulated Precepts (data & behavior). It can throw errors or warn -- AND -- assign a default value to the Implementor class.
iAbstractClass
The iAbstractClass defines the interface to be used. Its approach entails a tacit agreement with its Implementor class. This interface assigns each precept to the same exact precept namespace -- OR -- to whatever the Precept Resolver function returns. However, the tacit agreement resolves to a context -- a provision of Implementor.
Implementor
The Implementor simply 'agrees' with an Interface (iAbstractClass in this case) and applies it by the use of Constructor-Hijacking: iAbstractClass.apply(this). By defining the data & behavior above, and then hijacking the Interface's constructor -- passing Implementor's context to the Interface constructor -- we can ensure that Implementor's overrides will be added, and that Interface will explicate warnings and default values.
This is a very non-cumbersome approach which has served my team & I very well for the course of time and different projects. However, it does have some caveats & drawbacks.
Drawbacks
Though this helps implement consistency throughout your software to a significant degree, it does not implement true interfaces -- but emulates them. Though definitions, defaults, and warnings or errors are explicated, the explication of use is enforced & asserted by the developer (as with much of JavaScript development).
This is seemingly the best approach to "Interfaces in JavaScript", however, I would love to see the following resolved:
Assertions of return types
Assertions of signatures
Freeze objects from delete actions
Assertions of anything else prevalent or needed in the specificity of the JavaScript community
That said, I hope this helps you as much as it has my team and I.
Hope, that anyone who's still looking for an answer finds it helpful.
You can try out using a Proxy (It's standard since ECMAScript 2015): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
latLngLiteral = new Proxy({},{
set: function(obj, prop, val) {
//only these two properties can be set
if(['lng','lat'].indexOf(prop) == -1) {
throw new ReferenceError('Key must be "lat" or "lng"!');
}
//the dec format only accepts numbers
if(typeof val !== 'number') {
throw new TypeError('Value must be numeric');
}
//latitude is in range between 0 and 90
if(prop == 'lat' && !(0 < val && val < 90)) {
throw new RangeError('Position is out of range!');
}
//longitude is in range between 0 and 180
else if(prop == 'lng' && !(0 < val && val < 180)) {
throw new RangeError('Position is out of range!');
}
obj[prop] = val;
return true;
}
});
Then you can easily say:
myMap = {}
myMap.position = latLngLiteral;
If you want to check via instanceof (asked by #Kamaffeather), you can wrap it in an object like so:
class LatLngLiteral {
constructor(props)
{
this.proxy = new Proxy(this, {
set: function(obj, prop, val) {
//only these two properties can be set
if(['lng','lat'].indexOf(prop) == -1) {
throw new ReferenceError('Key must be "lat" or "lng"!');
}
//the dec format only accepts numbers
if(typeof val !== 'number') {
throw new TypeError('Value must be numeric');
}
//latitude is in range between 0 and 90
if(prop == 'lat' && !(0 < val && val < 90)) {
throw new RangeError('Position is out of range!');
}
//longitude is in range between 0 and 180
else if(prop == 'lng' && !(0 < val && val < 180)) {
throw new RangeError('Position is out of range!');
}
obj[prop] = val;
return true;
}
})
return this.proxy
}
}
This can be done without using Proxy but instead the classes getters and setters:
class LatLngLiteral {
#latitude;
#longitude;
get lat()
{
return this.#latitude;
}
get lng()
{
return this.#longitude;
}
set lat(val)
{
//the dec format only accepts numbers
if(typeof val !== 'number') {
throw new TypeError('Value must be numeric');
}
//latitude is in range between 0 and 90
if(!(0 < val && val < 90)) {
throw new RangeError('Position is out of range!');
}
this.#latitude = val
}
set lng(val)
{
//the dec format only accepts numbers
if(typeof val !== 'number') {
throw new TypeError('Value must be numeric');
}
//longitude is in range between 0 and 180
if(!(0 < val && val < 180)) {
throw new RangeError('Position is out of range!');
}
this.#longitude = val
}
}
abstract interface like this
const MyInterface = {
serialize: () => {throw "must implement serialize for MyInterface types"},
print: () => console.log(this.serialize())
}
create an instance:
function MyType() {
this.serialize = () => "serialized "
}
MyType.prototype = MyInterface
and use it
let x = new MyType()
x.print()
You need interfaces in Java since it is statically typed and the contract between classes should be known during compilation. In JavaScript it is different. JavaScript is dynamically typed; it means that when you get the object you can just check if it has a specific method and call it.
When you want to use a transcompiler, then you could give TypeScript a try. It supports draft ECMA features (in the proposal, interfaces are called "protocols") similar to what languages like coffeescript or babel do.
In TypeScript your interface can look like:
interface IMyInterface {
id: number; // TypeScript types are lowercase
name: string;
callback: (key: string; value: any; array: string[]) => void;
type: "test" | "notATest"; // so called "union type"
}
What you can't do:
Define RegExp patterns for type value
Define validation like string length
Number ranges
etc.
there is no native interfaces in JavaScript,
there are several ways to simulate an interface. i have written a package that does it
you can see the implantation here
Try this: Describe the interface as a class and use #implements JSDoc to show that a given class implements the interface defined. You'll see red squiggly lines on the class name if its not implementing some properties. I tested with VSCode.
// #ts-check
// describe interface using a class
class PlainInterface {
size = 4;
describe() {}
show(){ }
}
/**
* #implements PlainInterface
*/
class ConcretePlain {
size = 4;
describe() {
console.log('I am described')
}
show(){
console.log('I am shown')
}
}
const conc = new ConcretePlain();
conc.describe();
Javascript does not have interfaces. But it can be duck-typed, an example can be found here:
http://reinsbrain.blogspot.com/2008/10/interface-in-javascript.html
This is an old question, nevertheless this topic never ceases to bug me.
As many of the answers here and across the web focus on "enforcing" the interface, I'd like to suggest an alternative view:
I feel the lack of interfaces the most when I'm using multiple classes that behave similarly (i.e. implement an interface).
For example, I have an Email Generator that expects to receive Email Sections Factories, that "know" how to generate the sections' content and HTML. Hence, they all need to have some sort of getContent(id) and getHtml(content) methods.
The closest pattern to interfaces (albeit it's still a workaround) I could think of is using a class that'll get 2 arguments, which will define the 2 interface methods.
The main challenge with this pattern is that the methods either have to be static, or to get as argument the instance itself, in order to access its properties. However there are cases in which I find this trade-off worth the hassle.
class Filterable {
constructor(data, { filter, toString }) {
this.data = data;
this.filter = filter;
this.toString = toString;
// You can also enforce here an Iterable interface, for example,
// which feels much more natural than having an external check
}
}
const evenNumbersList = new Filterable(
[1, 2, 3, 4, 5, 6], {
filter: (lst) => {
const evenElements = lst.data.filter(x => x % 2 === 0);
lst.data = evenElements;
},
toString: lst => `< ${lst.data.toString()} >`,
}
);
console.log('The whole list: ', evenNumbersList.toString(evenNumbersList));
evenNumbersList.filter(evenNumbersList);
console.log('The filtered list: ', evenNumbersList.toString(evenNumbersList));
With an interface you can implement a way of polymorphism. Javascript does NOT need the interface type to handle this and other interface stuff. Why? Javascript is a dynamically typed language. Take as example an array of classes that have the same methods:
Circle()
Square()
Triangle()
If you want to know how polymorphism works the Book MFC of David Kruglinsky is great (written for C++)
Implement in those classes the method draw() push the instances of those classes in the array and call the draw() methods in a loop that iterates the array. That's completely valid. You could say you implemented implicitly an abstract class. Its not there in reality but in your mind you did it and Javascript has no problem with it. The difference with an real interface is that you HAVE to implement all the interface methods and that's in this case not needed.
An interface is a contract. You will have to implement all the methods. Only by making it statically you have to do that.
Its questionable to change a language like Javascript from dynamic to static. Its not mend to be static. Experienced developers have no problems with the dynamic nature of Javascript.
So the reason to use Typescript are not clear to me. If you use NodeJS together with Javascript you can build extremely efficient and cost effective enterprise websites. The Javascript/NodeJS/MongoDB combination are already great winners.
I know this is an old one, but I've recently found myself needing more and more to have a handy API for checking objects against interfaces. So I wrote this: https://github.com/tomhicks/methodical
It's also available via NPM: npm install methodical
It basically does everything suggested above, with some options for being a bit more strict, and all without having to do loads of if (typeof x.method === 'function') boilerplate.
Hopefully someone finds it useful.
This is old but I implemented interfaces to use on ES6 without transpiller.
https://github.com/jkutianski/ES6-Interfaces
It bugged me too to find a solution to mimic interfaces with the lower impacts possible.
One solution could be to make a tool :
/**
#parameter {Array|object} required : method name list or members types by their name
#constructor
*/
let Interface=function(required){
this.obj=0;
if(required instanceof Array){
this.obj={};
required.forEach(r=>this.obj[r]='function');
}else if(typeof(required)==='object'){
this.obj=required;
}else {
throw('Interface invalid parameter required = '+required);
}
};
/** check constructor instance
#parameter {object} scope : instance to check.
#parameter {boolean} [strict] : if true -> throw an error if errors ar found.
#constructor
*/
Interface.prototype.check=function(scope,strict){
let err=[],type,res={};
for(let k in this.obj){
type=typeof(scope[k]);
if(type!==this.obj[k]){
err.push({
key:k,
type:this.obj[k],
inputType:type,
msg:type==='undefined'?'missing element':'bad element type "'+type+'"'
});
}
}
res.success=!err.length;
if(err.length){
res.msg='Class bad structure :';
res.errors=err;
if(strict){
let stk = new Error().stack.split('\n');
stk.shift();
throw(['',res.msg,
res.errors.map(e=>'- {'+e.type+'} '+e.key+' : '+e.msg).join('\n'),
'','at :\n\t'+stk.join('\n\t')
].join('\n'));
}
}
return res;
};
Exemple of use :
// create interface tool
let dataInterface=new Interface(['toData','fromData']);
// abstract constructor
let AbstractData=function(){
dataInterface.check(this,1);// check extended element
};
// extended constructor
let DataXY=function(){
AbstractData.apply(this,[]);
this.xy=[0,0];
};
DataXY.prototype.toData=function(){
return [this.xy[0],this.xy[1]];
};
// should throw an error because 'fromData' is missing
let dx=new DataXY();
With classes
class AbstractData{
constructor(){
dataInterface.check(this,1);
}
}
class DataXY extends AbstractData{
constructor(){
super();
this.xy=[0,0];
}
toData(){
return [this.xy[0],this.xy[1]];
}
}
It's still a bit performance consumming and require dependancy to the Interface class, but can be of use for debug or open api.
Js doesn't have interfaces but typescript does!
While there isn't a interface in javaScript as there is in Java you could mimic the behaviour a bit with the code under this message. because an interface is basicly an enforced contract you could build it yourself.
The code below exists out of 3 classes an interface, parent and child class.
The Interface has the methods to check if the methods and properties exist required exist.
The Parent is used to enforce the required methods and properties in the child using the Interface class.
The Child is the class that the parents rules are enforced on.
After you set it up correctly you will see an error in the console if a method or property is missing in the child and nothing if the child implements the contract correctly.
class Interface {
checkRequiredMethods(methodNames) {
setTimeout( () => {
const loopLength = methodNames.length;
let i = 0
for (i; i<loopLength; i++) {
if (typeof this[methodNames[i]] === "undefined") {
this.throwMissingMethod(methodNames[i]);
}
else if (typeof this[methodNames[i]] !== "function") {
this.throwNotAMethod(methodNames[i]);
}
}
}, 0);
}
checkRequiredProperties(propNames) {
setTimeout( () => {
const loopLength = propNames.length;
let i = 0
for (i; i<loopLength; i++) {
if (typeof this[propNames[i]] === "undefined") {
this.throwMissingProperty(propNames[i]);
}
else if (typeof this[propNames[i]] === "function") {
this.throwPropertyIsMethod(propNames[i]);
}
}
}, 0);
}
throwMissingMethod(methodName) {
throw new Error(`error method ${methodName} is undefined`);
}
throwNotAMethod(methodName) {
throw new Error(`error method ${methodName} is not a method`);
}
throwMissingProperty(propName) {
throw new Error(`error property ${propName} is not defined`);
}
throwPropertyIsMethod(propName) {
throw new Error(`error property ${propName} is a method`);
}
}
class Parent extends Interface {
constructor() {
super()
this.checkRequiredProperties([
"p1",
"p2",
"p3",
"p4",
"p5"
]);
this.checkRequiredMethods([
"m1",
"m2",
"m3",
"m4"
]);
}
}
class Child extends Parent {
p1 = 0;
p2 = "";
p3 = false;
p4 = [];
p5 = {};
constructor() {
super();
}
m1() {}
m2() {}
m3() {}
m4() {}
}
new Child()
No, but it has mixins.
You can use Abstract sub-classss or mixins as an alternative https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#mix-ins