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");
Related
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.
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
}
This question already has answers here:
Accessing an object property with a dynamically-computed name
(19 answers)
Closed 3 years ago.
i need to return this.
GetBooking = function (parameter) {
return Booking.Title[0].parameter;
}
GetPages = function () {
return GetBooking(pages)
}
GetNumber = function () {
return GetBooking(number)
}
booking is a object of arrays, is possible?
If I understand correctly, when doing GetBooking(pages) you expect to get in return Booking.Title[0].pages, meaning GetBooking() function is supposed to be like a middleman to decide which property you want to get from Booking.Title[0].
If I'm correct, then you almost had it right. What will happen in your code is, for example if number was 7, it would look for a property named 7 inside Booking.Title[0].
What you really want to do is this: return Booking.Title[0][parameter], and parameter has to be a string value representing the property you're looking for, meaning you also need to change the rest of the code which would ultimately look like this:
GetBooking = function (parameter) {
return Booking.Title[0][parameter];
}
GetPages = function () {
return GetBooking("pages") ;
}
GetNumber = function () {
return GetBooking("number") ;
}
This will take the string in parameter and look for a property that matches that string inside Booking.Title[0], and return its value.
This question already has answers here:
JavaScript classes with getter and setter cause RangeError: Maximum call stack size exceeded
(5 answers)
Closed 6 years ago.
I want to convert Mike Herchel's Importing CSS Breakpoints into ES6 class. For this, I chose to use get and set to finally learn how to.
My code so far:
export default class Breakpoints {
constructor() {
this.value = null;
this.refreshValue();
window.addEventListener('resize', () => {
this.refreshValue();
});
}
refreshValue() {
let val = window.getComputedStyle(document.querySelector('body'), ':before').getPropertyValue('content').replace(/\"/g, '');
this.value = val;
}
set value(val) {
this.value = val;
}
get value() {
return this.value;
}
}
Problem is, when I run it, I am getting Maximum call stack size exceeded. Where I did go wrong?
There's absolutely no reason to use getters/setters here, they don't do anything else than a normal property would do.
When I run it, I am getting Maximum call stack size exceeded. Where I did go wrong?
Your getter returns the value of the property again, thereby invoking itself. Your settter sets the value of the property again, thereby invoking itself. Don't do that.
If you really wanted to use getters for some reason, go for
export default class Breakpoints {
constructor() {
this._val = null;
this.refreshValue();
window.addEventListener('resize', () => {
this.refreshValue();
});
}
refreshValue() {
this._val = window.getComputedStyle(document.querySelector('body'), ':before').getPropertyValue('content').replace(/\"/g, '');
}
get value() {
return this._val;
}
// no `value` setter, because it can't be changed from outside
}
So here's the object 'playerTurnObj'
function playerTurnObj(set_turn) {
this.playerTurn=set_turn;
function setTurn(turnToSet) {
this.playerTurn=turnToSet;
}
function getTurn() {
return this.playerTurn;
}
}
and here is what I'm doing with it
var turn = new playerTurnObj();
turn.setTurn(1);
so I try to make the script do the setTurn() method in playerTurnObj() to save a 'turn' in a game I'm making. The problem is, it does not do the turn.setTurn(1); part because I keep getting the error above
what am I doing wrong? I searched, but I could not find an exact answer to my question.
This is not the way JavaScript works. Your "constructor" function contains inline functions that are not visible outside of the scope of playerTurnObj. So your variable turn does not have a method setTurn defined, as the error message states correctly. Probably you want something like this:
function playerTurnObj(set_turn) {
this.playerTurn=set_turn;
}
playerTurnObj.prototype = {
setTurn: function(turnToSet) {
this.playerTurn=turnToSet;
},
getTurn: function() {
return this.playerTurn;
}
};
Now your variable turn has two methods setTurn and getTurn that operate on the instance you created with new.
The setTurn and getTurn functions are private so they return undefined rather than invoking the function. You can do:
function playerTurnObj(set_turn) {
this.playerTurn=set_turn;
this.setTurn = setTurn;
this.getTurn = getTurn;
function setTurn(turnToSet) {
this.playerTurn=turnToSet;
}
function getTurn() {
return this.playerTurn;
}
}
You then have public setTurn and getTurn methods and can invoke them as follows:
var turn = new playerTurnObj();
turn.setTurn(1);
http://jsfiddle.net/Ht688/
What I make out of it is you need to return the object this in function playerTurnObj(). So your new code will look something like:
function playerTurnObj(set_turn) {
this.playerTurn=set_turn;
function setTurn(turnToSet) {
this.playerTurn=turnToSet;
}
function getTurn() {
return this.playerTurn;
}
return this;
}