Javascript (ES6), destructure based off variable - javascript

I am wondering to see if there is a way to destructure objects in javascript with using a variable. Where as I was doing something like this in my function -
mutateTaxon(data) {
const { content } = data;
const { plp } = content || {};
...
This was working fine, however I need to expand this function based off another factor that can change if I need to use data.content (which it is using now) or data.collection. So I have another node on the data - which changes call to call. I am trying something like this -
mutateTaxon(data) {
const match = lowerCase(data.taxonomy.name);
const { match } = data;
const { plp } = match || {};
Where that match variable would evaluate to either content or collection (as expected). This does not seem to work however, maybe it is not possible? I was thinking maybe the match var needed to be evaluated so I tried something like -
const { [[match]] } = data;
which also is not working. Maybe this is not possible, or I am approaching this wrong. I am wondering, is something like this possible? Thanks!

The destructuring syntax would, as Jonas W. said, be a bit more cumbersome than the bracket notation, but nonetheless, this is how you would do it:
mutateTaxon(data) {
const key = lowerCase(data.taxonomy.name);
const { [key]: { plp } = {} } = data;
Demo
const foo = { bar: { plp: 'success' } }
const key = 'bar'
const { [key]: { plp } = {} } = foo
console.log(plp)
And to confirm that default parameter = {} works as expected:
const foo = { }
const key = 'bar'
const { [key]: { plp } = {} } = foo
console.log(plp)

const key = lowerCase(data.taxonomy.name);
const match = data[key];
I dont think that object destructuring is useful here. But if you need that:
const key = lowerCase(data.taxonomy.name);
const {[key]: match} = data;

Related

Change Object Index

Is there way to change the index dynamically? or rebuild this object to where the 1 will be the Id of what ever object get passed into the function? Hope this makes sense.
export const createTree = (parentObj) => {
//keep in memory reference for later
const flatlist = { 1: parentObj }; <---- change the 1 based on parent.Id
...
}
My attempt thinking it would be easy as:
const flatlist = { parentObj.Id: parentObj };
Use computed property names to create a key from an expression:
const createTree = (parentObj) => {
const flatlist = { [parentObj.id]: parentObj };
return flatlist;
}
console.log(createTree({ id: 1 }));

Null Check for destructured Variables in object

I have the code shown below for destructuring end_time property from this.props.auction object
const {auction: {auction: {end_time}}} = this.props;
But the issue here is above constant will be undefined if auction is an empty object. To fix this, I have changed the code to
if(Object.keys(this.props.auction).length) {
var {auction: {auction: {end_time}}} = this.props;
} else {
var {end_time} = "";
}
The above solution works but is ugly and I believe there is definitely a far better way of doing it.
Followed the answer from this post and
My attempt so far is:
const {auction: {auction: {end_time = null}}} = this.props || {};
I thought the above one will set end_time by default to null but I guess since auction is not defined it is throwing an error.
Please suggest a better way of declaring the end_time constant which takes care of an empty auction
You don’t need to use destructuring every time you can use it.
const auction = this.props.auction.auction;
const end_time = auction === undefined ? null : auction.end_time;
You could potentially use destructuring with default values like this:
const { auction: { auction: { end_time = null } = {} } = {} } = this.props || {};
But because the syntax above is cumbersome and unnatural to follow, I ultimately yield to Ry's advice in this case:
You don’t need to use destructuring every time you can use it.
I realize this is tagged ecmascript-6, but this question presents a great example where using the optional chaining operator and nullish coalescing operator seems the most natural solution, at least when they become officially merged into the ECMAScript 2020 specification:
const end_time = this.props?.auction?.auction?.end_time ?? null;
By combining the use of Optional chaining and Nullish Coalescing Operator you can achieve this goal with only one line like this:
const end_time = props.auction?.auction?.end_time ?? '';
Below are few testing functions to understand the concept:
const end_time_defaultValue = 'end_time_defaultValue';
function testWithEndTime() {
const props = {
auction: {
auction: {
end_time: new Date(),
kay1: 'value1',
kay2: 'value2'
}
}
};
const end_time = props.auction?.auction?.end_time ?? end_time_defaultValue;
console.log('testWithEndTime() => ', end_time);
}
testWithEndTime();
// outputs the today date
function testWithoutEndTime() {
const props = {
auction: {
auction: {
kay1: 'value1',
kay2: 'value2'
}
}
};
const end_time = props.auction?.auction?.end_time ?? end_time_defaultValue;
console.log('testWithoutEndTime() => ', end_time);
}
testWithoutEndTime();
// outputs the end_time_defaultValue
// because the key 'end_time' does not exist
function testWithoutAuctionAuction() {
const props = {
auction: {
}
};
const end_time = props.auction?.auction?.end_time ?? end_time_defaultValue;
console.log('testWithoutAuctionAuction() => ', end_time);
}
testWithoutAuctionAuction();
// outputs the end_time_defaultValue
// because the key 'auction.auction' does not exist
function testWithoutPropsAuction() {
const props = {};;
const end_time = props.auction?.auction?.end_time ?? end_time_defaultValue;
console.log('testWithoutPropsAuction() => ', end_time);
}
testWithoutPropsAuction();
// outputs the end_time_defaultValue
// because the key 'props.auction' does not exist
Be careful about browsers compatibility
But if you're using a framework like React, babel will do the job for you.
You may do de-structuring in 2 steps: first de-structure your props, then the necessary object that could be undefined at certain point in component life-cycle.
// instead of
const {auction: {auction: {end_time}}} = this.props;
// you may do
const { auction } = this.props;
let end_time;
if(auction){
({ end_time } = auction);
}

Am doing the destructing right?

I have a coding challenge, which am sure am getting it right , but the challenge requires that certain steps need to be in account before moving forward. And i seem to be skipping a step which is to de-structure a value from a target of an event(hope am saying it right)
The question is to get the expected event parameter to the target property with a de-structure.
Is my code wrong?
const displaySelectedUser = (event) => {
var newcal = event.target.value;
console.log(newcal);
console.log((event.target.value));
var user = getSelectedUser(newcal);
var properties = Object.keys(user);
console.log(properties);
properties.forEach(prop => {
const span = document.querySelector(`span[data-${prop}-value]`);
if (span) {
span.innerText = user[prop];
}
});
};
It's not wrong - but the only practical opportunity you have for destructuring is here:
var newcal = event.target.value;
Do this:
var { target: { value: newcal } } = event;
Because you're not using the other properties of event, you could move this up to the function declaration instead:
const displaySelectedUser = ({ target: { value: newcal } }) => {...}
Now newcal will already be defined as event.target.value in your function.

Javascript arrow notation functions undefined syntax error

I am new to javascript, i trying to learn to js, here i am getting syntax error while console the output
const screemwarriors = () => {
var warriors = "Ninja";
shootwarriors = function(){
console.log(warriors);
}
}
const output = screemwarriors();
console.log(output.shootwarriors());
Here i am getting syntax error
Looks like your trying to access the result as an object. You must return the function in an object if you intend to do it in this way.
Update: cleaned up code
const screemwarriors = () => ({
shootwarriors: () => {
console.log("Ninja");
}
});
const output = screemwarriors();
output.shootwarriors();
Cheers,
Your calling code will work if you modify your function like this:
const screemwarriors = function() {
var warriors = 'Ninja';
return {
shootwarriors: function() {
return warriors;
}
}
}
const output = screemwarriors();
console.log(output.shootwarriors());

How to build a namespace-like string using chained variables

This is a strange one, but I'm exploring it to see if it's possible.
Let's say that I have a .NET application where I am using PubSub. I want a way to define the topic string using chained objects (not functions). The goal is to allow me a way of defining strings that lets me to take advantage of Visual Studio's IntelliSense and reduce the likelihood of spelling errors.
Here's an example:
/* Manual way */
var topic = "App.Navigation.CurrentItem"
/* Desired Solution */
// ... define the objects here ...
var topic = App.Navigation.CurrentItem;
console.log(topic); // "App.Navigation.CurrentItem"
var topic2 = App.Footer.CurrentItem;
console.log(topic2); // "App.Footer.CurrentItem"
I'd like each object to be responsible for outputing it's own value, and have the chaining process responsible for joining itself to the previous chained object via a predefined separator (in my case, a period [.]).
I've been playing with JavaScript getter syntax, but I'm curious if there's a better way.
Has anyone done something like this before, and if so, how did you solve it?
You're requirements aren't totally clear to me, but are you looking for something like this?
function namespace(ns) { this._ns = ns; }
namespace.prototype.toString = function() {return this._ns};
namespace.prototype.extend = function(suffix) {
return new namespace(this._ns + "." + suffix)
};
Usage:
App = new namespace('App');
App.Navigation = App.extend('Navigation');
App.Navigation.CurrentItem = App.Navigation.extend('CurrentItem');
console.log(App.Navigation.CurrentItem.toString()); // "App.Navigation.CurrentItem"
This is what I ended up with after reviewing StriplingWarrior's answer:
function Namespace(name, config) {
if (typeof name === "object") {
config = name;
name = null;
}
config = config || {};
this._ns = name;
this.define(config);
}
Namespace.prototype.toString = function() { return this._ns };
Namespace.prototype.define = function(config, base) {
base = base || this;
for (key in config) {
var name = (base._ns) ? base._ns + "." + key : key;
base[key] = new Namespace(name);
base.define(config[key], base[key]);
}
return base;
};
Usage:
var App = new Namespace("App", {
Navigation: {
Items: {
Current: {}
}
},
Content: {},
Footer: {
Items: {
Current: {}
}
}
});
console.log(App.toString()); // App
console.log(App.Navigation.Items.Current.toString()); // App.Navigation.Items.Current
console.log(App.Footer.toString()); // App.Footer
I also wrote a convenience method to reduce the toString():
function NS(namespace) {
return namespace.toString();
}
console.log(NS(App.Navigation.Items.Current));
Thanks again to StriplingWarrior for the the help!

Categories