This question already has answers here:
Javascript Object destructuring and default parameters combined
(3 answers)
Closed 2 years ago.
Just looking over a cool tutorial and there was a notation that I didn't completely understand and having a hell of a time trying to google it.
async function mapEffect({ leafletElement: map } = {}) {
let response;
try {
response = await axios.get(‘https://corona.lmao.ninja/countries’);
} catch(e) {
console.log(`Failed to fetch countries: ${e.message}`, e);
return;
}
// this next line here is the one confusing me:
const { data = [] } = response;
}
Reading on, it appears that data is just an array - any reason it is written like this? Can anyone explain in layman's terms why you would write something this way? I never stop learning... Thank you!
const { data = [] } = response;
is equal to
// [] is default value if response.data is empty
const data = response.data || [];
What that piece of code is doing is destructuring an object.
Destructuring lets you bind variables to different properties of an object. When you specify the property being bound, it will then be followed by the variable you are binding its value to.
Here is a basic example:
const { foo, bar } = { foo: "hello", bar: "world" };
console.log(foo);
console.log(bar);
//1st letter
console.log(foo[0]);
console.log(bar[0]);
In your case it has a default value as fallback ( [] an array in case your response comes empty)
You can read more about it here
Related
This question already has answers here:
What's the difference between passing by reference vs. passing by value?
(18 answers)
Closed last year.
EDIT 2: Why has this very specific question been marked as a duplicate of this very conceptual one: What's the difference between passing by reference vs. passing by value?. If someone else had the same question as me, they wouldn't end up with this one on Google by searching for it and - even if they did - it wouldn't answer their question.
EDIT: Thanks everyone for your help so far. Pretty difficult stuff to understand from my point of view. The reason I'm doing this is that I've set up a function which I'm calling multiple times and in which I define a variable (a unique one with each call). I need to be able to refer back to each unique variable afterwards. Here is my actual attempted code below. What would the right way to do this be?
let newSeq1
let newSeq2
function sequenceClip(sample, length, sequenceVariable) {
let currentPosition = Tone.Transport.position
let whenToStart
if (currentPosition === '0:0:0') {
whenToStart = '0:0:0'
} else {
const barToStartOn = +currentPosition.slice(0, currentPosition.indexOf(':'))
whenToStart = `${barToStartOn + 1}:0:0`
}
sequenceVariable = new Tone.Sequence((time, note) => {
sampler.triggerAttackRelease(note, '4m', time)
}, [sample], length).start(whenToStart);
}
loop1.addEventListener('mousedown', () => {
sequenceClip("C3", '1m', newSeq1)
})
loop2.addEventListener('mousedown', () => {
sequenceClip("C#3", '4m', newSeq2)
})
How do I pass a variable into a function in Javascript to be assigned a value. E.g.:
Why does the variable not get assigned the value 5? And what's the way around this?
let a
function defineVariable(var2beDefined) {
var2beDefined = 5
}
defineVariable(a)
console.log(a === 5)
You would typically write an initializer function that returns a value and assign that return value to the relevant global variable. For example:
let newSeq1
let newSeq2
function sequenceClip(sample, length, sequenceVariable) {
let currentPosition = Tone.Transport.position
let whenToStart
if (currentPosition === '0:0:0') {
whenToStart = '0:0:0'
} else {
const barToStartOn = +currentPosition.slice(0, currentPosition.indexOf(':'))
whenToStart = `${barToStartOn + 1}:0:0`
}
return new Tone.Sequence((time, note) => {
sampler.triggerAttackRelease(note, '4m', time)
}, [sample], length).start(whenToStart);
}
loop1.addEventListener('mousedown', () => {
newSeq1 = sequenceClip("C3", '1m')
})
loop2.addEventListener('mousedown', () => {
newSeq2 = sequenceClip("C#3", '4m')
})
Note that both newSeq1 and newSeq2 will be undefined until the first mousedown/mouseup events.
Reassigning an identifier, by itself, never has any side-effects (in most circumstances) - the only change resulting from someIdentifier = someNewValue will be when other parts of the code reference that same someIdentifier.
If you want to pass in something to be assigned to, pass in a function which, when called, assigns to the outer variable.
let a;
function defineVariable(callback) {
callback(5);
}
defineVariable(newVal => a = newVal);
console.log(a === 5)
The only time that assigning to an identifier will have side effects is if:
Inside a function with a simple argument list, you reassign one of the parameters (in which case the arguments object will be changed as well)
You're using ES6 modules, and you reassign an identifier that's being exported, in which case other modules that import it will see the change as well
This question already has an answer here:
How to destructure option argument with all default values in ES6?
(1 answer)
Closed 3 years ago.
I have a problem with referencing to data with this while trying to declare default parameters combined with destructuring. Anyone knows how to do it?
activated () {
this.fillData()
},
data () {
return {
chartData: {
distributionInitialData: {
// data here
}
}
}
},
methods: {
fillData ({
must = this.chartData.distributionInitialData,
nice = this.chartData.distributionInitialData
}) {
// do something
// function doesn't even get here because it gets error:
// TypeError: Cannot read property 'must' of undefined
// at VueComponent.fillData (Component.vue?4e6a:230)
// at VueComponent.activated (Component.vue?4e6a:123)
}
}
You need to set the default value for the parameter(Object), but not to its properties.
methods: {
fillData ({must, nice} = {
must: this.chartData.distributionInitialData,
nice: this.chartData.distributionInitialData
}) {
// do something
}
}
Updated by Bergi's advice.
methods: {
fillData ({
must: this.chartData.distributionInitialData,
nice: this.chartData.distributionInitialData
} = {}) {
// do something
}
}
FYI, here is a simple codepen.
You can do.
fillData ({ must, nice}) {
must = must || this.chartData.distributionInitialData
nice = nice || this.chartData.distributionInitialData
// do something
}
So the issue has to do with how Vue binds the methods to the component as it is created. The function definition does not have access to the instance, but inside of it you may use this.
The easiest solution would be to do an immediate check for undefined and set based on the desired default.
fillData({ must, nice }) {
if (must === undefined) must = this.chartData.distributionInitialData;
if (nice === undefined) nice = this.chartData.distributionInitialData;
// any other code here
}
You might also try playing around with arrow functions to see if it fixes this, since that was introduced to be bound to this in a more concrete way. Perhaps something like this:
fillData = ({
must = this.chartData.distributionInitialData,
nice = this.chartData.distributionInitialData
}) => {
// any other code here
}
I came across this piece of code here, and I noticed that const data is declared inside the brackets. I thought you had to use the key: value format inside the brackets when creating an object. How does this work?
data = {
const data = await d3.tsv("https://gist.githubusercontent.com/mbostock/8033015/raw/01e8225d4a65aca6c759fe4b8c77179f446c5815/unemployment.tsv", (d, i, columns) => {
return {
name: d.name.replace(/, ([\w-]+).*/, " $1"),
values: columns.slice(1).map(k => +d[k])
};
});
return {
y: "% Unemployment",
series: data,
dates: data.columns.slice(1).map(d3.utcParse("%Y-%m"))
};
}
That is not valid javascript. The reason it works is that Observable has its own syntax. It's deliberately designed to be similar to javascript, but it isn't actually javascript. You can read more about this here:
https://observablehq.com/#observablehq/observables-not-javascript
The code above is not a valid javascript code.
observableHQ is using its own parser to achieve that https://github.com/observablehq/parser the code is translated to the following:
const chart = (arguments) => {
// code...
}
I am improving my React js code, using ESLint with eslint-config-airbnb, I am getting errors of type:
[eslint] Must use destructuring props assignment (react/destructuring-assignment)
I am able to overcome these errors by using JS Object destructuring and if necessary declaring additional variables.
In the following snippet, I use object destructuring to populate the cat variable. However, if I want to do an "if" statement, conditionally against the object destructuring output, I am unable to do that without doing a 2 step process where:
Declare the variable to use populating it via object destructuring
Use that variable in my "if" statement.
Is there some way to do this without having to declare this "temporary" variable, but still access the inner object property via object destructuring for use within for example an "if" statement.
I have made an attempt below, with the commented code, but it does not compile.
const animals = {
cat: "brown",
dog: "white"
};
let cat;
({
cat
} = animals);
console.log(cat);
if (cat === "brown") {
console.log("The cat is brown");
};
// Now, the same "if" statement, but this time I replace the variable called "cat" with lines 6 to 8 above
/*
if (({
cat
} = animals) === "brown")) {
console.log("The cat is brown");
};
*/
Here is the actual code which is having the error, I just constructed the example above to focus on the js syntax:
aTest() {
if (this.state.shouldToggle === true) {
this.setState({ activeTabKey: 'hello' })
} else {
clearInterval(this.state.timerId)
}
}
this.state.shouldToggle - is underlined red with the error "[eslint] Must use destructuring state assignment (react/destructuring-assignment)"
To me, it's very strange that ESLint complains about not using destructuring there. But apparently it does, which means your choices are:
Disable the rule if you don't like its requirements. (If it really requires use of destructuring in that code — and I have no reason to doubt your screenshot — the rule seems a bit silly to me, but that's neither here nor there.)
Since it's requiring you to use destructuring, in that example it's requiring you to use destructuring assignment (since you have no parameters to destructure), which means you have to have something to assign to, which means creating unnecessary variables/constants:
aTest() {
const {shouldToggle, timerId} = this.state;
if (shouldToggle === true) {
this.setState({ activeTabKey: 'hello' })
} else {
clearInterval(timerId)
}
}
That prevents repeating this.state, but makes you repeat shouldToggle and timerId instead, which doesn't seem like a useful trade-off (again, to me, but my opinion isn't what matters here, yours is).
As per your updated question, you should just be able to do:
aTest() {
const { shouldToggle, timerId } = this.state
if (shouldToggle) {
this.setState({ activeTabKey: 'hello' })
} else {
clearInterval(timerId)
}
}
Continuing with your previous try:
if (({ cat } = animals) === "brown")) {
console.log("The cat is brown");
};
Will never satisfy the condition.
When you assign a variable using destructuring syntax, it is comparing with object itself. Let me clarify you using simple tests:
if(({test} = {test:13})==13) {
console.log(test); // will not be logged
}
if(({test} = {test:13})==undefined) {
console.log(test); // will not be logged
}
if(({test} = {test:13})==true) {
console.log(test); // will not be logged
}
if(({test} = {test:13})==false) {
console.log(test);
}
if(JSON.stringify(({test} = {test:13})) == JSON.stringify({test:13}) ) {
console.log(test); // now, this will be logged
}
So, you're comparing brown == { cat: 'brown', dog: 'white' } which will never satisfy.
What you must do implement is to assign them in a variable using destructuring syntax as per ESLINT,
const { cat } = animals
if(cat === 'brown') { // Okay
This question already has answers here:
Is it possible to achieve dynamic scoping in JavaScript without resorting to eval?
(7 answers)
Closed 5 years ago.
For example. I have this code:
export const mergeWrapper = function(aFunction, meta) {
return aFunction;
};
function exampleFunction(temp) {
console.log(temp);
// can print here. without changing exampleFunction method signature.
// in this case should be 'stackoverflow'
console.log(meta);
}
mergeWrapper(exampleFunction, 'stackoverflow')('hello');
I want to do "something" in mergeWrapper. so that, inside aFunction, I can call meta. I have tried something such as:
export const mergeWrapper = function(aFunction, meta) {
aFunction.bind(this);
return aFunction;
};
But it doesn't work. How can I do this.
My idea because I can write some sort of this function using currying. for example:
export const wrapperFunction = function(meta) {
return function(temp) {
console.log(temp);
console.log(meta);
}
}
wrapperFunction('StackOverFlow')('hello');
But written like this will make me write wrapper for all functions. So I want to write a helper.
Thanks
You can do
const mergeWrapper = function(aFunction, meta) {
return aFunction.bind(null, meta);
};
function exampleFunction(meta, temp) {
console.log(temp);
// can print here. without changing exampleFunction method signature.
// in this case should be 'stackoverflow'
console.log(meta);
}
let func = mergeWrapper(exampleFunction, 'stackoverflow');
func('temp');
func('temp2');
Where you have binded meta as the first argument, and all calls would get that value of meta