Vue.js default function parameter destructuring and 'this' [duplicate] - javascript

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
}

Related

Pass an object that has an optional property to a function that guarantee it will not be undefined but editor/compiler still think it can be undefined

function f1(
toolbox: {
tool1?: Tool1,
tool2?: Tool2,
}
) {
if (!toolbox.tool1) {
toolbox.tool1 = fetchTool1();
}
if (!toolbox.tool2) {
toolbox.tool2 = fetchTool2();
}
// Do something else
}
function f2(
toolbox: {
tool1?: Tool1,
tool2?: Tool2,
}
) {
f1(toolbox);
// tool1 and tool2 are no longer undefined.
const x = toolbox.tool1.value // Editor shows error, tool1 may be undefined.
}
The design above passes a toolbox object to different functions, so the program doesn't need to fetch the tools that are already fetched by other functions. The problem is, even if I know for sure toolbox.tool1 and toolbox.tool2 will not be undefined after calling f1, the editor still shows error.
I know I can use exclamation mark like const x = toolbox.tool1!.value, or maybe just turn off the warning. But I'm looking for a way that is more friendly to the default type checking.
I have tried let f1 return the toolbox that has no question mark in it, and call toolbox = f1(toolbox). It doesn't work, the line const x = toolbox.tool1.value still shows error.
You're looking for asserts.
f1 now looks like this:
function f1(
toolbox: {
tool1?: Tool1,
tool2?: Tool2,
}
): asserts toolbox is { tool1: Tool1; tool2: Tool2 } {
You can think of this as "changing" the type in the scope it was called:
f1(toolbox);
toolbox // now { tool1: Tool1; tool2: Tool2 }
const x = toolbox.tool1.value; // fine
Playground

how to add a new key value to the same key in an object in JavaScript based on a condition?

I have done it using ...qqParam['queryParams'] but is this the right approach?
const qqParam = {};
if (view) {
qqParam['queryParams'] = { view: view };
}
if (productNumber) {
qqParam['queryParams'] = { ...qqParam['queryParams'], mode: 'productNumber' };
}
I think your approach is correct, just a couple things that can simplify your code while keeping it readable:
if you know you'll always need queryParam attribute, you can call it like this: qqParam.queryParam without the [], if the key of the attribute is dynamic then you're doing it ok by passing it as a variable qqParam[variable].
you're in both ifs modifying the same value so you might consider doing that on one statement:
qqParam.queryParams = {
...(view && {view}),
...(productNumber && {mode:'productMode' })
};
Your sample code works but you can simplify it.
You don't need to use the square brackets when assigning a property to the object unless it contains a symbol, a special character or a computed property name.
const qqParam = {};
if(view) {
qqParam.queryParams = { view };
}
if(productNumber) {
qqParam.queryParams = { ...qqParam.queryParams, mode: 'productNumber' };
}
Your approach is fine. one improve that you can do is not to use : {'view' : view}.
you can just use {view} as the default key will be the value name when you not specifing one.
Also, i guess that 'productNumber' should be the variable productNumber and not the string 'productNumber'.
const qqParam = {};
if (view) {
qqParam['queryParams'] = { view };
}
if (productNumber) {
qqParam['queryParams'] = { ...qqParam['queryParams'], mode: productNumber };
}

Odd javascript notation - what does it mean? [duplicate]

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

Two classes one with reference to function to another different this value

I have problem and I don't know how to solve it:
this.bWords.push(word);
^
TypeError: Cannot read property 'push' of undefined
here is my code:
function multiWords(words) {
class AWords {
constructor(words = []) {
this.words = words;
this.addWordFn = () => {};
}
setAddWordFn(fn) {
this.addWordFn = fn;
}
passWords() {
this.words.forEach(word => this.addWordFn(word));
}
}
class BWords {
constructor() {
this.bWords = [];
}
addWord(word) {
this.bWords.push(word);
}
}
let x = new AWords(words);
let y = new BWords();
x.setAddWordFn(y.addWord);
x.passWords();
return y.bWords;
}
console.log(multiWords(["one", "two", "three"]));
Do you have any ideas why there is different this value?
Many thanks
Pati
It appears that the problem occurs here:
this.words.forEach(word => this.addWordFn(word));
because the function you've set for addWordFn here:
x.setAddWordFn(y.addWord);
Needs a different value of this than you are calling it with. You can fix it by binding the right value of this to your callback:
x.setAddWordFn(y.addWord.bind(y));
Remember that for regular functions, the value of this inside the function is determined by how the function is called. When you call a function with obj.method(), the this value inside of method() will be set to obj. So, you're calling addWord with the wrong this value because you've made it a method of some other object (that does not also have the data it needs) and are calling it off that object.

How to call getter of javascript as string [duplicate]

This question already has answers here:
Accessing an object property with a dynamically-computed name
(19 answers)
Closed 3 years ago.
i am writing a code to automate android and IOS using webdriverio
I have a piece of js code where i have defined some getter and depending upon the user input, i want to call a getter
var assert = require('assert')
const Page = require('./Page.js')
const SELECTORS = {
ANDROID: {
landing_header: '~landing_header',
sys_house: '~sys_house',
aero_center: '~aero_center',
},
IOS: {
//IOS Page Object
},
}
class Landing extends Page {
get landingHeader() {
return browser.isAndroid ? $$(SELECTORS.ANDROID.landing_header)[0] : $$(SELECTORS.ANDROID.landing_header)[0]
}
get sysHouseTile() {
return browser.isAndroid ? $$(SELECTORS.ANDROID.sys_house)[0] : $$(SELECTORS.ANDROID.sys_house)[0]
}
get settingsCenterTile() {
return browser.isAndroid ? $$(SELECTORS.ANDROID.aero_center)[0] : $$(SELECTORS.ANDROID.aero_center)[0]
}
navigateLandingPage(page) {
if(page=="settings") {
var lObj=eval(page+"CenterTile");
this.settingsCenterTile.click();//this is working fine
this.lObj.click();//this is not working
}
browser.pause(3000)
}
}
module.exports = new Landing()
navigateLandingPage() method is being called from another js file
Now my issue is depending on the page input,
i want to click any one method
and i can update the getter runtime, but don't know how to call it.
this.lObj.click()
Do not use eval() for this, you can use the computed property syntax object[propName] to dynamically invoke getters.
Just take a look at my sample code below, in the getters I am returning a function when it is invoked. When I accessed the property dynamically I invoked the getter and it returned me a function and i executed that:
class Landing{
get landingHeader() {
return () => {
console.log("landingHeader");
}
}
get sysHouseTile() {
return () => {
console.log("sysHouseTile");
}
}
get settingsCenterTile() {
return () => {
console.log("settingsCenterTile");
}
}
navigateLandingPage(page) {
if(page=="settings") {
var lObj = this[page+"CenterTile"]();
}
}
}
new Landing().navigateLandingPage("settings");

Categories

Resources