I'm looking for a way to do the following:
var test = 'I exist!';
var testNull = null;
var testUndefined;
function checkVar(varToCheck) {
return typeof varToCheck != 'undefined' && varToCheck != null;
}
console.log(checkVar(test)); // Logs true
console.log(checkVar(testNull)) // Logs false
console.log(checkVar(testUndefined)) // Logs false
console.log(checkVar(undefinedVar)) // Logs false
When it tries to execute the last line, instead of false, this throws an error: Uncaught ReferenceError: undefinedVar is not defined.
I know it can be done with:
if (typeof varToCheck != 'undefined' && varToCheck != null) {
alert('something happens!')
}
but it's becoming annoyingly repetitive to use long conditions in my project, once I have a lot of variables to check. Any ideas?
typeof is unnecesary. also, !== will check specifically for the type and not just falsy/truthy values.
function checkVar(varToCheck) {
return varToCheck !== undefined && varToCheck !== null;
}
undefinedVar is not a variable with an undefined value, it was never declared to begin with, and will throw an error if you try reference it.
However, object properties that weren't declared will not throw an error if you try reference them, and will compute to undefined.
What I was looking for was a secure way to access values of nested objects.
I ended up using a tiny lib called Typy, which provided exactly the functionality I needed.
I will leave Typy and some other alternatives I've found:
Typy
Lodash's _.get
get-value
Related
I am using immutable.js to manage configuration object, e.g.
config.js
export default Immutable.fromJS({
foo: 'FOO',
bar: {
// ...
}
});
I would like to overwrite the getter functions so that accessing an undefined property would throw an error.
How do I do it given that every setter method of the resulting object will create a new instance of Immutable (in effect overwriting whatever monkey-patching)?
Generally I do not want it to throw an error, just handle undefined without causing the code to break fatally. To throw specific error I might use try/catch, but this is highly inefficient.
To prevent breakage I do something like this.
My motivation here is mostly that my call .get of undefined poops itself really hard, and initializing properly all over the place helps, but doesn't catch all edge cases. I just want the data or undefined without any breakage. Specific type checking causes me to do more work later if I want it to make changes.
This looser version solves many more edge cases(most if not all extend type Iterable which has .get, and all data is eventually gotten) than a specific type check does(which usually only saves you when you try to update on the wrong type etc).
/* getValid: Checks for valid ImmutableJS type Iterable
returns valid Iterable, valid Iterable child data, or undefined
Iterable.isIterable(maybeIterable) && maybeIterable.get(['data', key], Map()), becomes
getValid(maybeIterable, ['data', key], Map())
But wait! There's more! As a result:
getValid(maybeIterable) returns the maybeIterable or undefined
and we can still say getValid(maybeIterable, null, Map()) returns the maybeIterable or Map() */
export const getValid = (maybeIterable, path, getInstead) =>
Iterable.isIterable(maybeIterable) && path
? ((typeof path === 'object' && maybeIterable.getIn(path, getInstead)) || maybeIterable.get(path, getInstead))
: Iterable.isIterable(maybeIterable) && maybeIterable || getInstead;
//Here is an untested version that a friend requested. It is slightly easier to grok.
export const getValid = (maybeIterable, path, getInstead) => {
if(valid(maybeIterable)) { // Check if it is valid
if(path) { // Check if it has a key
if(typeof path === 'object') { // Check if it is an 'array'
return maybeIterable.getIn(path, getInstead) // Get your stuff
} else {
maybeIterable.get(path, getInstead) // Get your stuff
}
} else {
return maybeIterable || getInstead; // No key? just return the valid Iterable
}
} else {
return undefined; // Not valid, return undefined, perhaps should return false here
}
}
Just give me what I am asking for or tell me no. Don't explode. I believe underscore does something similar also.
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 have a variable that in some cases isn't declared, and I want to use it in a jQuery template. This is what I am trying to achieve, but it throws an *payment_method is not defined* exception:
{{if payment_method && (payment_method.id == $value.id)}}
// this throws an exception when payment_method is undeclared!
{{/if}}
This works:
{{if payment_method }}
{{if payment_method.id == $value.id}}
// nested works!
{{/if}}
{{/if}}
but I'm not too keen of a nested solution since I use it alot. I clearly understand why the first case throws the error, what I am looking for is a possible workaround for this without resorting to the second solution.
This issue probably boils down to problems in js to check properties for undeclared/undefined variables. This works:
if("undefined" !== typeof undefinedVariable) {
// this works just fine also for undeclared variables
}
but this doesn't:
if("undefined" !== typeof undefinedVariable.property) {
// this throws an exception
}
Any ideas?
When using an undefined/undeclared variable it doesn't throw any exceptions, but using it's properties does. This is where it gets a bit fuzzy though.
If you check for the existence of this undeclared variable by typeof, it evaluates to false (at least I think so, it does so when being the only condition...) and does not continue to check for further conditions. If you only check for it's existence by it's name, it evaluates to false, but the next condition gets evaluated none the less...
Anyhow, this does not throw any exception:
if(typeof undeclaredVariable !== "undefined" && typeof undeclaredVariable.property !== "undefined") {
// this works just fine
}
and neither does:
if(typeof undeclaredVariable !== "undefined" && undeclaredVariable.property) {
// this also works just fine but is shorter
}
but this does:
if (undeclaredVariable && undeclaredVariable.property) {
// the conditional clause does not stop at undeclaredVariable but also checks for undeclaredVariable.id where it throws an exception
}
Without understanding the true mechanisms of how conditions get evaluated, the answer to my question is (successfully tested):
{{if typeof payment_method !== "undefined" && payment_method && (payment_method.id == $value.id)}}
EDIT: Using an undefined/undeclared variable throws an exception in js, but it does not in jQuery tmpl.
js:
if (undeclaredVariable) {
// throws an exception
}
jQuery tmpl:
{{if undeclaredVariable}}
// evaluates to false, but does not throw an exception
{{/if}}
Here is what you need, working in best way.
try {
if (!! someVariable)
{
//its declared you can use it
}
else
{
//its not declared
}
}
catch (e) {
//its not declared
}
You can use the hasOwnProperty function to check for the existence of a property on an object.
See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/HasOwnProperty
The trouble in js is you need to check the property exists first before you can test anything against it, so it make condition a bit messier.
{{if payment_method && payment_method.id && (payment_method.id == $value.id)}}
var foo;
var bar = 'defined';
try{
if(someVariable === 'undefined') {
console.log('undefined'); //foo
}else{
console.log('declare && defined'); //bar
}
}catch (e){
console.log('undeclared'); //undeclaredVariable
}
{{if this.data.payment_method && this.data.payment_method.id == $value.id}}{{/if}}
I'm trying to make some existing JS backwards compatible. I need to override a method if it does not exist, otherwise just return the existing method.
Here is the code I have so far:
this.grid.getDataSource = function(){
if (getDataSource == undefined)
return getStore();
else
return getDataSource();
}
However it keeps returning an error on the "if" line:
getDataSource is undefined
What is the best way of going about this?
This should work without throwing an error.
if (typeof getDataSource != "function")
you might need to wrap it in a typeof() function
this.grid.getDataSource = function(){
if (typeof getDataSource == undefined)
return getStore();
else return getDataSource();
}
this.grid.getDataSource = getDataSource || getStore;
Here is a nice resourse, which should answer to your question. It's a pretty simple function.
http://phpjs.org/functions/method_exists:471
This is a follow up question to This Question.
I like (and understand) the solution there. However, in the code I am working in, another way to solve the same problem is used:
function exist(sFN) {
if(self[sFN]) return true;
return false;
}
It seems to work fine, although I don't understand how. Does it work? How? What are minuses of this approach? Should I switch to solution from the other question?
Try this:
function exist(sFN) {
return (typeof sFN == 'function');
}
Your condition is checking the existence of the "sFN" property in the "self" object. Anything that isn't null, undefined, 0, and "" will evaluate to true.
As others have said, you can use typeof, or instanceof to see if it's actually a function.
Looking at your linked example, you should read up on the difference between ==/!= and ===/!== in javascript. Short answer: ("" == null) is true, ("" === null) is false.
just use typeof.
typeof(foobar) // -> undefined
typeof(alert) // -> function
You can't, however, defined a function based on typeof, because you'd need to pass an identifier which might not exist. So if you define function isfun(sym) { return typeof(sym) }, and then tried calling isfun(inexistent), your code would throw.
The fun thing about typeof is that it's an operator, not a function. So you can use it to check a symbol that's not defined without throwing.
if you assume a function in the global scope (i.e., not within a closure), you can define a function to check it as follows:
function isfun(identifier) {
return typeof(window[identifier]) == 'function';
}
Here you pass an string for the identifier, so:
isfun('alert'); // -> true
isfun('foobar'); // -> false
closure?
Here's an example of a function defined within a closure. Here, the printed value would be false, which is wrong.
(function closure() {
function enclosed() {}
print(isfun('enclosed'))
})()
FYI: There is (or was) a nice pitfall for typeof.
FF2 returns 'function' for typeof(/pattern/).
FF3, IE7, and Chrome all return 'object' for the same code.
(I can't verify other browsers.)
Assuming everyone that used FF2 has upgraded, you're in the clear.
But, that's probably a far-fetched assumption.
You can't really wrap this in a method, but it's so simple there is really no need.
function bob()
{}
if( typeof bob == "function" )
alert( "bob exists" );
if( typeof dave != "function" )
alert( "dave doesn't" );
Object.prototype.toString.apply(value) === '[object Function]'
I read somewhere (here and here) that functions are properties of the window object, so you can do the following:
if (window.my_func_name) {
my_func_name('tester!');
}
or for popups:
if (window.opener.my_func_name) {
my_func_name('tester!');
}
A complete solution then:
function function_exists(func_name) {
var eval_string;
if (window.opener) {
eval_string = 'window.opener.' + func_name;
} else {
eval_string = 'window.' + func_name;
}
return eval(eval_string + ' ? true : false');
}