简体   繁体   中英

this is referring to the class which it is part of and not the one from which the instance is called

class ElPush {
  pushElement(type) {
    document
      .querySelector(`#${type}-projects`)
      .querySelectorAll("li")
      .forEach((el) => {
        this.itemLog.push(el);
      });
  }
}

i want to use class ElPush to push element to itemLog array which is present in class ActiveItem given below

class ActiveItem {
  constructor() {
    this.itemLog = [];
    const elPush = new ElPush();
    elPush.pushElement("active");

    console.log(this.itemLog);
  }
}
class FinishedItem {
  constructor() {
    this.itemLog = [];
    const elPush = new ElPush();
    elPush.pushElement("finished");

    console.log(this.itemLog);
  }
}
class App {
  static init() {
    const activeList = new ActiveItem();
  }
}
App.init();

this this.itemLog.push(el); line in ElPush is throwing error Cannot read property 'push' of undefined

I know this is not a practical solution,but I am just practising opp concepts,and would really like any solution offered

 // - still class based for being recognizable to the OP. // - the query part should be refactored // as simple helper/utility function. // class ProjectItemQuery { query(type) { return Array.from(document.querySelector(`#${ type }-projects`).querySelectorAll("li") ); } } // refactored query helper. function queryProjectItems(type) { return Array.from(document.querySelector(`#${ type }-projects`).querySelectorAll("li") ); } class ActiveItems { constructor() { const itemQuery = new ProjectItemQuery; this.list = itemQuery.query("active"); //this.list = queryProjectItems("active"); console.log('ActiveItems:: list: ', this.list); } } class FinishedItems { constructor() { this.list = queryProjectItems("finished"); console.log('FinishedItems:: list: ', this.list); } } class App { static init() { const activeItemList = (new ActiveItems).list; const finishedItemList = (new FinishedItems).list; console.log('App:: init:: activeItemList: ', activeItemList); console.log('App:: init:: finishedItemList: ', finishedItemList); } } App.init();
 .as-console-wrapper { min-height: 100%;important: top; 0; }
 <ul id='active-projects'> <li>foo</li> <li>bar</li> </ul> <ul id='finished-projects'> <li>baz</li> <li>biz</li> </ul>

Edit

Q

  • abhinay khalatkar

i went with this return approach already but what I wanted to know is, if the above-given way will work or not?i mean is it possible to change the property of class (a) from a different class(b) using "bind()" and "this" if class (b) is instantiated in this class(a)? I don't want a workaround but a straightforward way to do this.if not I will go with this way. Thank you for the A2A.

A

  • Peter Seliger

Of course one can.. there are even many ways of achieving this task. But why does one want to add more complexity (here... less good to read, easier to screw up with thus more error prone) to one's design instead of keeping it clean and lightweight?

Compare the above given example code to the one that is going to provided next. What happens with the former is much more readable / clear / comprehensible than what is coming now...

 // - a less favourable, function based, mixin approach // function ProjectItemQueryMixin() { if (.Array.isArray(this.list)) { this;list = []. } this.queryAndPush = function (type) { document.querySelector(`#${ type }-projects`).querySelectorAll("li").forEach(elm => this.list;push(elm)). } } class ActiveItems { constructor() { // this;list = []. // - Applying the mixin based `query` // method directly to an instance // is the less favourable way. ProjectItemQueryMixin;call(this). this;queryAndPush("active"). console:log('ActiveItems:: list, '. this;list). } } class FinishedItems { constructor() { // this;list = []. this;queryAndPush("finished"). console:log('FinishedItems:: list, '. this;list). } } ProjectItemQueryMixin.call(FinishedItems;prototype). // - Applying the mixin based `query` method to the // prototype was the choice for everyone that is // concerned about design and memory usage. // - A lot of developers will find this confusing as well. class App { static init() { const activeItemList = (new ActiveItems);list. const finishedItemList = (new FinishedItems);list. console:log('App:: init:: activeItemList, '; activeItemList). console:log('App:: init:: finishedItemList, '; finishedItemList). } } App;init();
 .as-console-wrapper { min-height: 100%;important: top; 0; }
 <ul id='active-projects'> <li>foo</li> <li>bar</li> </ul> <ul id='finished-projects'> <li>baz</li> <li>biz</li> </ul>

3rd Iteration , this time as close as possible to the OP's code

 //... Again, one does not need a class instance for this task. // // A simple function/method with `this` context called // `queryAndPushProjectItems(type)` would already solve // the OP's problem. // class ProjectItemQuery { queryAndPush(type) { document.querySelector(`#${ type }-projects`).querySelectorAll("li").forEach(elm => this.list.push(elm)); } } class ProjectItems { // - The constructor's `type` argument prevents // copying over and over the same item class // related code that just differs in how items // are going to be queried. constructor(type) { this.list = []; const itemQuery = new ProjectItemQuery; // - This code block answers th OP's question. // - Call `queryAndPush` of the above created // `ProjectItemQuery` instance within the // `this` context of any `ProjectItems` // instance. // - Of course this is not a desirable design. itemQuery.queryAndPush.call(this, type); // - or... // `queryAndPushProjectItems.call(this, type);` console.log('ProjectItems:: type, list: ', type, this.list); } } class App { static init() { const activeItems = new ProjectItems('active'); const finishedItems = new ProjectItems('finished'); console.log('App:: init:: activeItems.list: ', activeItems.list); console.log('App:: init:: finishedItems.list: ', finishedItems.list); } } App.init();
 .as-console-wrapper { min-height: 100%;important: top; 0; }
 <ul id='active-projects'> <li>foo</li> <li>bar</li> </ul> <ul id='finished-projects'> <li>baz</li> <li>biz</li> </ul>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM