Javascript shorthand to call method if object exists - javascript

I have a variable and if that variable is a object I would like to call a method on that object, if not I want to do nothing.
I'm wondering if there is any reason why I shouldn't do it like this.
var foo = null;
////////////////////////////////////////////////
// some code that could change foo to a object
////////////////////////////////////////////////
foo && foo.bar();

With ES6, you can combine optional chaining operator with call:
foo?.bar?.call()
If you want to pass arguments, keep in mind that the first one in call assigns this in function call
var foo = {
bar: function(x) { return x; }
};
first.value = foo?.bar?.call(0,42); // 42
second.value = foo?.baz?.call(0,42); // undefined, no error
<input id="first">
<input id="second">

The quick answer is yes, foo && foo.bar() won't throw an exception if foo is null, and if foo is non-null, bar() will be evaluated, and it's value will be the value of the expression.
Longer answer is that any value can be interpreted as a boolean, in the sense that every value is either truthy or falsey, and that the boolean operators do short-circuit evaluation -- left to right, if we see a false && or a true ||, there's no reason to carry on evaluating.
One last fact is that the value of boolean expression is the value of the expression where the short-circuit happened.

You need to assign an object to foo and a property with a function.
var foo;
foo = {};
foo.bar = function () {
console.log('inside bar');
};
foo && foo.bar && foo.bar();

((typeof foo === 'object') && foo.bar())
or
(!(typeof foo == 'object') || foo.bar())
If foo is of type object then execute.
See my answer here javascript using or operator to iterate over list of strings aswell.
This is a "common" issue for unintended behavior, if some uses assignments inside such a sequence and forgets that evaluation stops in the || sequence after first true , or stops after first false in the && .

Related

How does the var FOO = FOO || {} idiom in Javascript work?

From this question: What does "var FOO = FOO || {}" (assign a variable or an empty object to that variable) mean in Javascript?
I've learned that var FOO = FOO || {} essentially means "If FOO exists, then leave it untouched, else make it an empty object".
But how?
This is how I would parse this syntax:
var FOO = (FOO || {})
So: If FOO exists AND evaluates to Boolean value of True, then (FOO || {}) will return True, so eventually FOO will be completely overwritten and will hold the Boolean value of True from now on.
Else (FOO || {}) will return to whatever Boolean value {} evalueates to. Since an empty object, which {} is, always evaluates to True...
Then in ANY case (FOO || {}) should evaluate to True, so...
In ANY POSSIBLE CASE, after evaluating var FOO = FOO || {}, FOO should hold the trivial Boolean value of True, regardless of whatever it was holding before. Essentially, to my understanding, var FOO = FOO || {} should be equivalent to var FOO = True.
Where is my mistake?
If FOO exists AND evaluates to Boolean value of True, then (FOO || {}) will return True
That isn't how the || operator works in JS.
A correct interpretation is:
If the left hand side is a true value, evaluate as the left hand side (i.e. FOO), otherwise evaluate as the right hand side (i.e. {}).
var zero = 0;
var one = 1;
var two = 2;
console.log(zero || two);
console.log(one || two);
So: If FOO exists AND evaluates to Boolean value of True, then (FOO || {}) will return True, so eventually FOO will be completely overwritten and will hold the Boolean value of True from now on.
That is wrong, but the below lines surprise you if your background is Strictly Typed Languages :)
The expression doesn't return a boolean value. It returns the expression that can be evaluated to true.
Here is the docs for the same
Returns expr1 if it can be converted to true; otherwise, returns expr2. Thus, when used with Boolean values, || returns true if either operand is true; if both are false, returns false.
Logical operators are typically used with Boolean (logical) values. When they are, they return a Boolean value. However, the && and || operators actually return the value of one of the specified operands, so if these operators are used with non-Boolean values, they may return a non-Boolean value.
Different examples given in docs might help you understand the above words.
o4 = false || (3 == 4) // f || f returns false
o5 = 'Cat' || 'Dog' // t || t returns "Cat"
o6 = false || 'Cat' // f || t returns "Cat"
o7 = 'Cat' || false // t || f returns "Cat"
o8 = '' || false // returns false
JavaScript || operator returns the expression itself not the boolean value. Here's a reference from Mozilla documentation
Returns expr1 if it can be converted to true; otherwise, returns
expr2. Thus, when used with Boolean values, || returns true if either
operand is true.
Reference :
Conversion to True in boolean depends on whether the expression evaluates to a Truthy value.
So: If FOO exists AND evaluates to Boolean value of True, then (FOO ||
{}) will return True
The problem of the concept is the cast. Here the Object is not cast to Boolean, JS leave it untouched.
So, If FOO is defined (FOO || {}) will return FOO and if is not defined will return {}
This is because of Short Circuit Evaluation.
Short-circuit evaluation says, the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression: when the first argument of the AND (&&) function evaluates to false, the overall value must be false; and when the first argument of the OR (||) function evaluates to true, the overall value must be true.
But if the first argument of AND function evaluates to true, the second argument has to be executed or evaluated to determine the value of expression; and when the first argument of OR function evaluates to false, the second argument has to be executed or evaluated to determine the value of the expression.
In-case of FOO || {};
This returns FOO if FOO evaluates to TRUE, because there is no need to evaluate second argument if first one is true.
This returns {} if FOO evaluates to FALSE, because the second argument need to be evaluated to get the value of the expression.
See here for more details..

Declaring a variable inside if statement in JavaScript

Why is the following not valid JavaScript?
if (var foo = (true || false)) {
console.log(foo);
}
When you declare a variable in JavaScript the assignment will return the value of the new variable, so you can do something like this:
if (foo = (true||false)) console.log('Hello!');
> Hello!
Now if you call foo it will have a value of true:
console.log(foo);
> true
You cannot use the var private word, because if is a statement, not a function. If you want to be sure about the scope of your variable, then you have to declare it first:
var foo;
if (foo = (true||false)) console.log('Hello!');
> Hello!
Take a look here:
http://www.ecma-international.org/ecma-262/5.1/#sec-12.5
then here:
http://www.ecma-international.org/ecma-262/5.1/#sec-11
And conclude that the syntax isn't valid because of:
http://www.ecma-international.org/ecma-262/5.1/#sec-12.2
in relation (or rather lack thereof) to the above.
Try this :
var foo = true || false;
if (foo) {
console.log(foo);
}
Place the declaration first and then check for the condition.
You can do like this:
var foo;//declare the variable first
if (foo = (true || false)) { //then assign the value for foo
console.log(foo);
}
You cannot create variable declaration inside if statement.

A while loop and the "this" object

The code below defines a custom method for the Object's prototype that uses the native method "hasOwnProperty" to find the owner of the passed in property.
Object.prototype.findOwnerOfProperty = function(propName){
var currentObject = this;
while (currentObject !==null){
if (currentObject.hasOwnProperty(propName)){
return currentObject;
}
}
}
My encounters with while loops have been usually of this format:
while ( x < 10 ){
// do stuff
x++;
}
Say I called the "findOwnerOfProperty" method on an object:
newObject.findOwnerofProperty(firstProp);
My questions are:
1) What happens to the "this" object while the loop is running?
2) What exactly is the loop iterating through?
3) What is the difference between the first while loop and the second while loop, where the second loop has an obvious increment that explicitly changes the counter 'x' and the first loop doesnt? Which part of the first code changes the "currentObject"?
What is the difference between the first while loop and the second while loop
The first while loop is an infinite loop because currentObject never changes.
Property names are resolved firstly on the object itself, then on the objects on it's [[Prototype]] chain. You can access that chain using Object.getPrototypeOf, so you might be able to do something like:
Object.prototype.findOwnerOfProperty = function(propName) {
var obj = this;
do {
if (obj.hasOwnProperty(propName)) {
return obj;
}
obj = Object.getPrototypeOf(obj);
} while (obj)
}
// Some tests
var obj = {foo:'foo'};
var x = obj.findOwnerOfProperty('foo');
console.log(x == obj); // true
// Find foo on Bar.prototype
function Bar(){}
Bar.prototype.foo = 'foo';
var bar = new Bar();
var p = Object.getPrototypeOf(bar);
console.log(bar.findOwnerOfProperty('foo') == Bar.prototype); // true
// Find toString on Object.prototpye
console.log(bar.findOwnerOfProperty('toString') === Object.prototype); // true
// Non-existant property
console.log(bar.fum); // undefined
console.log(bar.findOwnerOfProperty('fum')); // undefined
The above returns undefined if no such object is found, which seems appropriate given that null is at the end of all [[Prototype]] chains and returning null would suggest that the property was found there.
Note that Object.getPrototypeOf is ES5 so not in all browsers in use.
Edit
It's possible that the function will be called with a value of this that isn't an Object, e.g.:
bar.findOwnerOfProperty.call(null, 'bar');
The desired outcome might be undefined or perhaps a type error, however the actual result depends on whether the code is strict or not and the value provided.
Non–strict code—if this is a primitive, then it will be set to the result of applying the abstract ToObject operator to the primitive value (e.g. if it's a number, then effectively new Number(value), if it's a string, then new String(value)).
In the case of null and undefined, this is set to the global object (note that applying ToObject to null or undefined throws an error) so the wrong inheritance chain will be checked (i.e. the global object, not null) and possibly the global object will be returned.
The fix for both these cases is "RTFM" (well, if there was one…) since by the time any code is executed, this has already been set and it's impossible to check the original call.
Strict code—in this case the value of this is not modified so a check can be made to ensure it's an Object or Function and return undefined otherwise:
Object.prototype.findOwnerOfProperty = function(propName) {
var obj = this;
// Only applies to strict mode
if ((typeof obj != 'object' && typeof obj != 'function') || obj === null) return;
while (obj) {
if (obj.hasOwnProperty(propName)) {
return obj;
}
obj = Object.getPrototypeOf(obj);
}
}
So there may be different results for strict and non–strict mode, e.g.
bar.findOwnerOfProperty.call(7, 'toString');
returns undefined for strict code and Number (i.e. the Number constructor) for non–strict code (because 7 is converted to a Number object as if by new Number(7), and calling typeof on a Number object returns 'object').
To achieve consistency, for values other than null and undefined, the ToObject operator could be emulated for strict code. Alternatively, the non–strict version could operate only on values where typeof returns function or object. I'll leave that decision to anyone who actually wants to implement this in anger.

What does this bit of code mean? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Javascript Shorthand - What Does the '||' Operator Mean When Used in an Assignment?
var variable = obj1 || obj2;
Does it mean this?
var variable;
if (obj1)
{
variable = obj1;
}
else if (obj2)
{
variable = obj2:
}
Is it considered bad practise?
The || operator returns its left hand side if resolves to be a true value, otherwise it returns its right hand side.
So it means the same as:
var variable;
if (obj1){
variable = obj1;
} else {
variable = obj2:
}
Note else, not, else if.
It is a common pattern and not usually considered bad practise.
The gotcha is that you need to be sure you want if (obj) and not if (typeof obj !== "undefined").
Yup, that's what it means, and it's good practice
|| is a logical OR, so if obj1 = false you get false OR obj2 so the variable equals obj2
How || expression works
The expression a || b value is determined by the last partial evaluated to determine Boolean truth.
false || 1 is evaluated as 1 is the last one evaluated.
true || 0 is evaluated as true as it is the last one evaluated.
How obj is evaluated in Boolean context
For an object in the context of Boolean value, object is evaluated to true unless null. It means even {} === true.
Combine the above two explanation, var variable = obj1 || obj2 assigns the first none null object from obj1 and obj2 to variable.

typeof foo['bar'] !== 'undefined' vs. 'bar' in foo

What's the difference between the return values of these two expressions...
Expression 1: typeof foo['bar'] !== 'undefined'
Expression 2: 'bar' in foo
... assuming that these conditions are met:
foo is an object,
foo does not contain any properties that have the value undefined set explicitly.
The first tests the value of bar in foo.
The second tests for the existence of the bar property in foo.
var foo = {bar:undefined};
typeof foo['bar'] !== 'undefined'; // false
'bar' in foo; // true
EDIT:
To add some clarification from the comments below, the issue OP is having is that accessing the domConfig property of window.document throws an Error.
This is an issue not related to the typeof operator, but rather to a specific issue with Firefox.
The issue has been documented here as a bug (back in 2003).
A few notable comments from that report:
Zbigniew Braniecki [:gandalf] 2003-11-19 09:09:31 PST
then why it can be iterated with for-in ?
Boris Zbarsky (:bz) 2003-11-19 09:24:05 PST
Because it is defined as a property on the nsIDOM3Document interface. It's
just one that throws if you try to access its getter. ...
Zbigniew Braniecki [:gandalf] 2003-11-19 09:33:53 PST
... So what kind of bug is it?
The goal is to remove not implemented method/property from interface or to
implement it?!?
Boris Zbarsky (:bz) 2003-11-19 09:53:23 PST
The goal is to eventually implement this.
My reading of the spec suggests that they should be the same. The "in" operator semantics are defined in terms of making a call to the internal (conceptual) [[HasProperty]] method, which itself is defined in terms of [[GetProperty]]. When [[HasProperty]] returns "undefined", then the "in" operator results in boolean false; otherwise it's true. Based on the definition of what [[GetProperty]] is supposed to do, that means that an "undefined" result of a property access would have the same meaning.
Given the conditions you outline, there is no difference. Both should produce the same boolean result and should behave the same around prototype lookup.
Object.prototype.hasOwnProperty.call(null, foo, 'bar')
is another common idiom that does the same as those two but does not incude properties available only on the prototype.
var foo = {};
foo.bar = undefined;
console.log("bar" in foo); // true
console.log(typeof foo["bar"] !== "undefined"); // false
var Con = function() {};
Con.prototype.bar = undefined;
var foo = new Con;
console.log("bar" in foo); // true
console.log(typeof foo["bar"] !== "undefined"); // false
The in check is simply the same as using a for in loop and returning true if the key is in the for in loop.
[Edit] Didn't see your "don't explicity set it to undefined" condition.
var foo = {}
Object.defineProperty(foo, "bar", {
"value": 42,
"enumerable": false
});
console.log("bar" in foo); // true (in chrome & FF4)
console.log(typeof foo["bar"] !== 'undefined'); // true
I actaully expected the in test to fail if you set it as non-enumerable. Seems like they are the same.
var foo = {}
Object.defineProperty(foo, "bar", {
"value": 42,
"writable": false
});
console.log("bar" in foo); // true (in chrome & FF4)
console.log(typeof foo["bar"] !== 'undefined'); // true
Both test still work if the property is "readonly"
var foz = {}
Object.defineProperty(foz, "bar", {
"value": 42
});
var foo = Object.freeze(foz);
console.log("bar" in foo); // true (in chrome & FF4)
console.log(typeof foo["bar"] !== 'undefined'); // true
Freezing the object also doesn't break the tests.
Given those two conditions, the expressions should give you identical results, except if
foo has an EcmaScript 5 getter defined for the bar property. Since the first expression actually reads the property value, that getter will be invoked. The second expression merely checks for the existence of the property so there is no need to incoke any such getter.
you are targeting Internet Explorer 4.0 - the in operator wasn't added until JavaScript 1.4 ;)
Here's some sample code to illustrate the difference in supporting browsers (Chrome, IE9, FF4):
var foo = {};
Object.defineProperty(foo, "bar", {
"get": function () {document.write("Getter invoked!<br/>"); return foo;}
});
document.write('"bar" in foo -->' +
("bar" in foo));
document.write('<br/>');
document.write('typeof foo["bar"] !== "undefined" -->' +
(typeof foo["bar"] !== "undefined"));
document.write('<br/>');
the first one first checks existence of 'bar' key in foo (undefined is returned if it's not found), then checks the type of that key.
the second on checks only existence.

Categories