Considering the JavaScript below:
var foo = undefined;
if(foo?.bar == true){
console.log("Wow. Impossible...");
}
Is there a general programming term for the ?. following the foo variable?
This allows you to compare a member of a potentially null object without having to explicitly check if the variable is null.
I'd like to be able to see if this functionality exists in other languages, but I'm not really sure what to look up.
It is known as Optional Chaining in JS.
Ref:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
https://javascript.info/optional-chaining
It is known differently in different languages, e.g. in C# it is called Null-Conditional.
Related
This question already has answers here:
Null-safe property access (and conditional assignment) in ES6/2015
(11 answers)
Closed 2 years ago.
I've been programming a lot in Swift recently. Today I did some work in JavaScipt when question popped up to me:
Is there something similar to optional chaining in JavaScript? A way to prevent undefined is not an object without any variables?
Example:
function test(){
if(new Date() % 2){
return {value: function(){/*code*/}};
}
}
test().value();
will fail half of time because sometimes test returns undefined.
The only solution I can think of is a function:
function oc(object, key){
if(object){
return object[key]();
}
}
oc(test(), 'value');
I would like to be able to do something like:
test()?.value()
The part after the question mark is only executed if test returned an object.
But this is not very elegeant. Is there something better? A magic combination of operators?
Edit I know I could rewrite test to return something. But I'm wondering if there's something like optional chaining. I'm not interested in a particular solution to the above example. Something that I also can use if have no control over the function returning undefined.
This is currently a Stage 4 proposal you can check on the progress of it here:
https://github.com/tc39/proposal-optional-chaining
You can use the babel plugin today:
https://www.npmjs.com/package/babel-plugin-transform-optional-chaining
Update 11th January 2020:
Babel now supports optional chaining by default
https://babeljs.io/blog/2020/01/11/7.8.0
The Optional Chaining operator is spelled ?.. It may appear in three positions:
obj?.prop // optional static property access
obj?.[expr] // optional dynamic property access
func?.(...args) // optional function or method call
Notes:
In order to allow foo?.3:0 to be parsed as foo ? .3 : 0 (as required for backward compatibility), a simple lookahead is added at the level of the lexical grammar, so that the sequence of characters ?. is not interpreted as a single token in that situation (the ?. token must not be immediately followed by a decimal digit).
Also worth checking out:
https://github.com/tc39/proposal-nullish-coalescing
https://github.com/babel/babel/tree/master/packages/babel-plugin-proposal-nullish-coalescing-operator
In plain JavaScript you have to do type checks or structure your code so that you know an object will exist.
CoffeeScript, a language that compiles down to JavaScript, provides an existential operator ?. for safe chaining if you're willing to consider a preprocessed language.
There's another discussion here about why you can't reproduce this behavior in JS.
There is also a discussion on the ESDiscuss forums about adding an existential operator to a future version of JavaScript. It doesn't seem very far along though, certainly nowhere close to practical use. More of an idea at this point.
Optional chaining has landed in JS. We can use optional chaining via the ?. operator in object property access. It allows us to try accessing properties of objects which might not exists (i.e. are undefined) without throwing an error.
Here is a code example:
const obj = {
foo: {
bar: 1
}
};
// If we try to access property which doesn't exists
// it just returns undefined
console.log(obj.baz);
try {
// Now we try to access a property of undefined which throws an error
obj.baz.foz;
} catch (e) {
console.dir(e.message);
}
// Now we use the optional chaining operator ?.
// We get undefined instead of an error
console.log(obj.baz?.foz);
console.log(obj.foo?.bar);
You can use
test() && test().value();
or
var testResult = test();
testResult && testResult.value();
If you ask me this is most similar to Swift's optional chaining.
var Obj = {Prop: {name: 'peter'}}
console.log(Obj.Prop.name)
console.log(Obj?.Prop?.name)
In the first sentence, you're just accessing object properties. The problem with that is that if you find Prop to be something other than an object, it will throw an exception. That's the reason of the optional chainig operator.
Lets say you try to do Obj.Prop2.name.
You'll get Uncaught TypeError: Cannot read property 'name' of undefined
if Instead you did Obj.Prop2?.name, You'll only receive undefined as a value, instead of an exception.
This is particularly useful when accessing deeply nested properties.
WARNING: This is a relatively new JS feature that's not yet implemented in all browsers, so be careful while using it for production applications.
Optional Chaining is finally in the JavaScript standard!
Here are a few examples:
// properties
foo?.bar
foo?.bar()
foo?.bar.baz()
foo?.bar?.baz()
// indexing
foo?.[0]
foo?.['bar']
// check if a function is defined before invoking
foo?.()
foo.bar?.()
foo?.bar?.()
And this is way better than what most people use for manually checking for nulls
Instead of evaluating
foo?.bar
to this little code snippet we are all used to writing
foo ? foo.bar : null
it actually evaluates to
foo == null ? undefined : foo.bar
which works for all the falsey values like an empty string, 0 or false.
Unrelated to the question, but you might also be interested in the ?? operator.
It has a similar purpose as || except it only checks for null or undefined.
For example:
foo ?? bar
would be the same as:
foo != null ? foo : bar
This is a very new feature, so even thought a lot of users already use a browser that supports this you will still want to use a tool to convert it to an older version of javascript.
What about returning a noop function that does nothing when the condition isn't met?
function test(){
if(new Date() % 2){
return {value: function(){/*code*/}};
}
return {value: function(){ /* just return a type consistent with the function above */ }
}
You can always return this; if test is a object method.
But why do you want to prevent such errors by creating mock functions?
Does OO JS have a mechanism for casting instance objects to boolean? I would like to be able to use custom instance objects directly in conditionals, and make assertions along the lines of !!(new Foo(0)) === false, !!(new Foo(1)) === true.
Python has __nonzero__ and __len__ (see here)
Ruby has to_bool.
How does JS do this for String literals "" and zero 0?
No, JS does not provide a trap method for casting to boolean. Truthiness of a value is statically determined by the language rules and cannot be changed.
You should give your instances a method to be explicitly invoked like isValid(), isTruthy(), isEmpty() or whatever concept your object represents.
I tried googling but couldn't find a precise answer, so allow me to try and ask here. If the question does not seem proper, please let me know and I'll delete it.
In JS you've got three different way of writing certain build in functionalities:
str.length
str.toString()
parseInt(str)
I wonder if there is a reason behind these different ways of writing. As a new user I don't grasp why it couldn't be streamlined as: length(str) / toString(str) / parseInt(str) or with dot formulation.
I however think if I do know the reason behind these differences, it would give me a better understanding of JavaScript.
Length is one of the attributes of string in JavaScript. Hence you use string.length to get the length of the string.
toString is a function for string objects, hence we use stringobj.toString().
parsInt(str) is a global function which takes string as a parameter.
JavaScript is object-oriented, so there are functions or procedures which require first an object to use as this in their bodies. str.length is a property, both syntactically and semantically. It doesn't require any parameters and represents some quality of the object. obj.toString() is a method (a function attached to an object), which doesn't represent any characteristics of the object, but rather operates on its state, computes some new values, or changes the state of the object a lot. parseInt(str) is a "global" function, which represents an operation not attached to any type or object.
Under the hood, these three ways may be well implemented with just calling a function, passing this as the first parameter (like C# does, for example). The semantic difference is the important one.
So why not use just the third syntax, like for example PHP does? First, it doesn't bloat the global environment with lots of functions which only work for one specific case and type, allowing you to specify any new function you want without breaking the old functionality. Second, it ecourages you to use object-oriented concepts, because you can already see working objects and methods in the language, and can try to make something similar.
And why isn't parseInt a method? It can as well be str.toInt() without any issues, it's just the way JavaScript designers wanted it to be, although it seems also a bit logical to me to make it a static method Number.parseInt(str), because the behaviour of the function is relevant more to the Number type than the String type.
JavaScript is based around objects. Objects have properties (e.g. a User object may have name and age properties). These are what define the user and are related to the user. Properties are accessed via dot-notation or brackets notation (to access Eliott’s age, we’ll use either eliott.age or eliott['age'] — these are equivalent).
These properties can be of any type — String, Number, Object, you name it — even functions. Now the proper syntax to call a function in JS is to put round brackets: eliott.sayHello(). This snippet actually fetches Eliott’s sayHello property, and calls it right away.
You can see Eliott as a box of properties, some of which can be functions. They only exist within the box and have no meaning out of the box: what would age be? Whose age? Who’s saying hello?
Now some functions are defined at the global level: parseInt or isNaN for instance. These functions actually belong to the global box, named window (because legacy). You can also call them like that: window.parseInt(a, 10) or window.isNaN(a). Omitting window is allowed for brevity.
var eliott = {
name: 'Eliott',
age: 32,
sayHello: function () { console.log('Hello, I’m Eliott'); }
};
eliott.name; // access the `name` property
eliott.age; // access the `age` property
eliott.sayHello; // access the `sayHello` property
eliott.sayHello(); // access the `sayHello` property and calls the function
sayHello(eliott); // Reference error: `window.sayHello` is undefined!
Note: Some types (String, Number, Boolean, etc.) are not real objects but do have properties. That’s how you can fetch the length of a string ("hello".length) and reword stuff ("hello, Eliott".replace("Eliott", "Henry")).
Behaviour of these expressions is defined in ECMAScript grammar. You could read the specification to understand it thoroughly: ECMAScript2015 specification. However, as pointed out by Bergi, it's probably not the best resource for beginners because it doesn't explain anything, it just states how things are. Moreover I think it might be too difficult for you to be able to grasp concepts described in this specification because of the very formal language used.
Therefore I recommend to start with something way simpler, such as a very basic introduction to JavaScript: JavaScript Basics on MDN. MDN is a great resource.
But to answer your question just briefly:
str.length is accessing a property of the str object.
parseInt(str) is a function call
str.toString() is a call of a function which is a property of the str object. Such functions are usually named methods.
Functions and methods are in fact very similar but one of the differences (except for the obvious syntax difference) is that methods by default have context (this) set to refer to the object which they're part of. In this case inside of toString function this equals to str.
Note: Accessing a property (as in str.length) could in effect call a getter function but it depends on how the object is defined, and is in fact transparent for the user.
Well, I am not sure if I describe the problem clearly, currently I am using ExtJS to do some developing, I saw some objects are "singleton", such as "Ext.Viewport", In C++, I can get the address of the object to see if they are actually same object, in Python, I can use "id" function to get the hash code of the object, and In Java I have similar built-in function "hashCode" to check if the objects are really same object, is there similar ways in javascript for this? so if there are some functions or operator in javascript, then I can tell if the object in ExtJS defined as "singleton" is really referencing to the same object.
You don't need anything so complicated. If two values are the same object, then they will be equal.
var foo = {};
var bar = foo;
alert(foo == bar);
If they are different (even if identical) objects, they won't be.
var foo = {};
var bar = {};
alert(foo == bar);
Your question is not very clear, but I'll try to answer.
Javascript itself does not use unique identifiers for each object by default. You could add this if you wanted to.
Depending on your requirements, you could also use the typeof operator to compare the type.
ExtJs however, does use unique id's (either id or itemId) and also allows you to get the class name of the object that your using. So you could do this easily in ExtJs.
The answer depends on whether you are comparing the type of object, or the actual object instance itself.
This other SO answer may be beneficial
I think that I'm understanding you... but, did you check this JavaScript comparator ?
=== - equal value and equal type
!== - not equal value or not equal type
reference: Javascript comparators
If you want to know if two object references refer to the same single object instance, use ==.
If you want to do a deep comparison of the referenced objects to see if the objects contain all the same values, even if they are not the same object instance, use Lodash's _.isEqual(a, b) method.
could also convert both to json, and use something like jsonDiff: https://github.com/pkafel/json-diff
This question already has answers here:
Null-safe property access (and conditional assignment) in ES6/2015
(11 answers)
Closed 2 years ago.
I've been programming a lot in Swift recently. Today I did some work in JavaScipt when question popped up to me:
Is there something similar to optional chaining in JavaScript? A way to prevent undefined is not an object without any variables?
Example:
function test(){
if(new Date() % 2){
return {value: function(){/*code*/}};
}
}
test().value();
will fail half of time because sometimes test returns undefined.
The only solution I can think of is a function:
function oc(object, key){
if(object){
return object[key]();
}
}
oc(test(), 'value');
I would like to be able to do something like:
test()?.value()
The part after the question mark is only executed if test returned an object.
But this is not very elegeant. Is there something better? A magic combination of operators?
Edit I know I could rewrite test to return something. But I'm wondering if there's something like optional chaining. I'm not interested in a particular solution to the above example. Something that I also can use if have no control over the function returning undefined.
This is currently a Stage 4 proposal you can check on the progress of it here:
https://github.com/tc39/proposal-optional-chaining
You can use the babel plugin today:
https://www.npmjs.com/package/babel-plugin-transform-optional-chaining
Update 11th January 2020:
Babel now supports optional chaining by default
https://babeljs.io/blog/2020/01/11/7.8.0
The Optional Chaining operator is spelled ?.. It may appear in three positions:
obj?.prop // optional static property access
obj?.[expr] // optional dynamic property access
func?.(...args) // optional function or method call
Notes:
In order to allow foo?.3:0 to be parsed as foo ? .3 : 0 (as required for backward compatibility), a simple lookahead is added at the level of the lexical grammar, so that the sequence of characters ?. is not interpreted as a single token in that situation (the ?. token must not be immediately followed by a decimal digit).
Also worth checking out:
https://github.com/tc39/proposal-nullish-coalescing
https://github.com/babel/babel/tree/master/packages/babel-plugin-proposal-nullish-coalescing-operator
In plain JavaScript you have to do type checks or structure your code so that you know an object will exist.
CoffeeScript, a language that compiles down to JavaScript, provides an existential operator ?. for safe chaining if you're willing to consider a preprocessed language.
There's another discussion here about why you can't reproduce this behavior in JS.
There is also a discussion on the ESDiscuss forums about adding an existential operator to a future version of JavaScript. It doesn't seem very far along though, certainly nowhere close to practical use. More of an idea at this point.
Optional chaining has landed in JS. We can use optional chaining via the ?. operator in object property access. It allows us to try accessing properties of objects which might not exists (i.e. are undefined) without throwing an error.
Here is a code example:
const obj = {
foo: {
bar: 1
}
};
// If we try to access property which doesn't exists
// it just returns undefined
console.log(obj.baz);
try {
// Now we try to access a property of undefined which throws an error
obj.baz.foz;
} catch (e) {
console.dir(e.message);
}
// Now we use the optional chaining operator ?.
// We get undefined instead of an error
console.log(obj.baz?.foz);
console.log(obj.foo?.bar);
You can use
test() && test().value();
or
var testResult = test();
testResult && testResult.value();
If you ask me this is most similar to Swift's optional chaining.
var Obj = {Prop: {name: 'peter'}}
console.log(Obj.Prop.name)
console.log(Obj?.Prop?.name)
In the first sentence, you're just accessing object properties. The problem with that is that if you find Prop to be something other than an object, it will throw an exception. That's the reason of the optional chainig operator.
Lets say you try to do Obj.Prop2.name.
You'll get Uncaught TypeError: Cannot read property 'name' of undefined
if Instead you did Obj.Prop2?.name, You'll only receive undefined as a value, instead of an exception.
This is particularly useful when accessing deeply nested properties.
WARNING: This is a relatively new JS feature that's not yet implemented in all browsers, so be careful while using it for production applications.
Optional Chaining is finally in the JavaScript standard!
Here are a few examples:
// properties
foo?.bar
foo?.bar()
foo?.bar.baz()
foo?.bar?.baz()
// indexing
foo?.[0]
foo?.['bar']
// check if a function is defined before invoking
foo?.()
foo.bar?.()
foo?.bar?.()
And this is way better than what most people use for manually checking for nulls
Instead of evaluating
foo?.bar
to this little code snippet we are all used to writing
foo ? foo.bar : null
it actually evaluates to
foo == null ? undefined : foo.bar
which works for all the falsey values like an empty string, 0 or false.
Unrelated to the question, but you might also be interested in the ?? operator.
It has a similar purpose as || except it only checks for null or undefined.
For example:
foo ?? bar
would be the same as:
foo != null ? foo : bar
This is a very new feature, so even thought a lot of users already use a browser that supports this you will still want to use a tool to convert it to an older version of javascript.
What about returning a noop function that does nothing when the condition isn't met?
function test(){
if(new Date() % 2){
return {value: function(){/*code*/}};
}
return {value: function(){ /* just return a type consistent with the function above */ }
}
You can always return this; if test is a object method.
But why do you want to prevent such errors by creating mock functions?