is there any equivalent for PHP's "??" operation in javascript? [duplicate] - javascript

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?

Related

What does the myObj.param?.otherParam operator do and how is it used?

I was reading the fundamentals guide for React Navigation and in the section for passing parameters to routes I came across this bit of code that I've never seen before.
if (route.params?.post) {
// Do something
}
I've never seen the ? operator used that way, I've only used the ternary operator. When searching the only other thing I found is the nullish assignment operator ??=.
I fiddled with it in the console and it seems to check if param exists so that if it doesn't exist it doesn't error when asking for .post
My first thought was that is a ternary operator without the second argument, but the third argument appears to be required.
So my question is, in the above code block, what is the ? doing, what is that called, and how/when is it used?
Thanks
It's called optional chaining. You can use it to check if the preceding variable is null, so that you could spare yourself checking for null/undefined properties.
// want to access blub.test.smth
if(blub && blub.test) {
// possibly access blub.test.smth
const value = blub.test.smth;
}
vs
const value = blub?.test?.smth

What does this JavaScript expression mean?

I am working with react-navigation and I can't figure out the meaning of this syntax.
React.useEffect(() => {
if (route.params?.post) { <<<<<WHAT IS THIS ?
// Post updated, do something with `route.params.post`
// For example, send the post to the server
}
}, [route.params?.post]);
Does it work like obect.doesPropertyExist.subProperty or something else?
I have tried going through MDN documentation but can't find any reference to this type of syntax. I am not able to use similar syntax on a random object in my node REPL.
It is called Optional Chaining. Provided in MDN doc:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
The optional chaining operator (?.) permits reading the value of a
property located deep within a chain of connected objects without
having to expressly validate that each reference in the chain is
valid. The ?. operator functions similarly to the . chaining operator,
except that instead of causing an error if a reference is nullish
(null or undefined), the expression short-circuits with a return value
of undefined. When used with function calls, it returns undefined if
the given function does not exist.
if(route.params.post) then do something.
It checks if route.params has object post
It's called Optional Chaining operator. And it's shorthand for
route.params && route.params.post

How do we know when to call "value" as opposed to "value()"?

Have a look at the last two answers.
How can we determine without looking into any documentation that sliderinput.value is the right answer, and not sliderinput.value()?
Im coming from Java. Im used to call accessor methods.
What is "value" as opposed to "value()"?
What is sliderinput if not an object?
You can determine this by checking if value is a function:
typeof sliderinput.value === "function"
Javascript usually doesn't use getter functions like value(). If you want to use getters you can use the get syntax to create a getter function that can be called using normal property syntax. See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
In the context of this quiz you've posted, I suppose they just want you to know from the top of your head that value is a property in this case.
How can we determine without looking into any documentation that sliderinput.value is the right answer, and not sliderinput.value()?
You can try it and see.
You can test its type (with the typeof operator) to see if it is a function or something else.
… but reading the documentation, despite you dismissing it, is the correct approach.
Note that the attribute value of sliderinput is a string, so the options with parenthesis () are not valid and will throw an error. You could do that only if value were a function type variable, which is not.
Edit: as other members pointed out, you can use typeof to check the variable type; in this case it will be "string"

Beginner Module Pattern JavaScript - Parameters [duplicate]

I have noticed jQuery and related keynote plugins like jQuery.UI pass undefined as a parameter into anonymous functions used in their module definitions, like so:
(function($, undefined) { ... })(jQuery);
Alternatively, I have noticed other plugins recommended by jQuery and/or others do NOT pass undefined in as a parameter.
This is probably a silly question, but...
Shouldn't it always be available anyway? Why pass it in? Is there some sort of other purpose or trick going on here?
There are two reasons for that:
1) If undefined is a variable in the function scope rather than a global object property, minifiers can reduce it to a single letter thus achieving a better compression rate.
2) Before ES5*, undefined was a property of the global object without write-protection. So it could be overwritten, resulting in strange and unexpected behavior. You could do something like this:
var test = 123;
undefined = 123;
if (test === undefined){
// this will actually be true, since undefined now equals 123
}
By having an function argument undefined (the name actually does not matter) which you don't pass a parameter to, you could make sure you have a variable which really is undefined so you can test "undefinedness" against this variable.
Btw. the safest method to test for undefined is: typeof ( var ) === 'undefined'
(*) With EcmaScript 5, the global properties undefined, NaN and Infinity became readonly. So with its general adoption in all modern browsers - of course with the exception of IE 9 - overwriting those values was not possible anymore.
That is done to make sure that undefined always is undefined. In older versions of the ECMAScript spec (prior to ECMAScript 5), undefined wasn't a reserved word but a regular variable. In older browsers this would be allowed for instance:
undefined = 2; // Assign a different value to undefined
// Now this statement would be true
if (undefined == 2)
So to make sure that undefined is in fact undefined, even if some other "evil" script would have reassigned undefined with another value, you create a parameter that you call undefined, and then when you call the function, you make sure to not pass a value to that parameter - thus you can be sure that the variable undefined will always be undefined within your function.
So in the case of jQuery:
(function($, undefined) { ... })(jQuery);
They pass in jQuery and assign it to the $ variable for convenience, but then they don't pass a second value to the undefined parameter, thus undefined will be undefined.
Modern browsers
In modern browsers, undefined is a non-configurable, non-writable property per the ECMAScript 5 specification.
undefined is not a reserved word in javascript, it is simply a variable. jQuery is ensuring that if some bad developer overwrites the value of undefined in their javascript, then jQuery will ignore it and establish it's own variable, undefined, which is never passed a value (see the self-executing (jQuery) at the end) and is therefore actually undefined.

JavaScript "cannot read property "bar" of undefined [duplicate]

This question already has answers here:
Detecting an undefined object property
(50 answers)
Closed 8 years ago.
I've got a function that takes 3 parameters. The problem I have is one of the parameters is a property of a sometimes undefined value of an Object (i.e. it takes in thing.foo.bar, and sometimes thing.foo is undefined, so it can't access bar).
What's a way around this? Within the function's declaration, I have a conditional checking:
if (!parameterName), but the browser (Chrome) is still throwing an error that it can't read the bar property of undefined.
If an object's property may refer to some other object then you can test that for undefined before trying to use its properties:
if (thing && thing.foo)
alert(thing.foo.bar);
I could update my answer to better reflect your situation if you show some actual code, but possibly something like this:
function someFunc(parameterName) {
if (parameterName && parameterName.foo)
alert(parameterName.foo.bar);
}
Compound checking:
if (thing.foo && thing.foo.bar) {
... thing.foor.bar exists;
}
You can safeguard yourself either of these two ways:
function myFunc(thing) {
if (thing && thing.foo && thing.foo.bar) {
// safe to use thing.foo.bar here
}
}
function myFunc(thing) {
try {
var x = thing.foo.bar;
// do something with x
} catch(e) {
// do whatever you want when thing.foo.bar didn't work
}
}
In the first example, you explicitly check all the possible elements of the variable you're referencing to make sure it's safe before using it so you don't get any unplanned reference exceptions.
In the second example, you just put an exception handler around it. You just access thing.foo.bar assuming it exists. If it does exist, then the code runs normally. If it doesn't exist, then it will throw an exception which you will catch and ignore. The end result is the same. If thing.foo.bar exists, your code using it executes. If it doesn't exist that code does not execute. In all cases, the function runs normally.
The if statement is faster to execute. The exception can be simpler to code and use in complex cases where there may be many possible things to protect against and your code is structured so that throwing an exception and handling it is a clean way to skip execution when some piece of data does not exist. Exceptions are a bit slower when the exception is thrown.
Just check for it before you pass to your function. So you would pass:
thing.foo ? thing.foo.bar : undefined

Categories

Resources