JS嵌套原型访问父节点

时间:2019-06-28 08:04:57

标签: javascript class oop instance

根据以下代码,我在访问原型中的this变量时遇到了一个小问题。

var MyClass = function(number) {
  this.number = number || 4;
};
MyClass.prototype = {
  run: function() {
    //direct access to object
    console.log(this.number);

    //access to object with the "self" object
    var self = this;
    setTimeout(function() {
      console.log(self.number);
    }, 1000);

    //access to object with the "self" object as a parameter
    this.events.test_a(self);

    //here is the problem
    this.events.test_b();
  },
  events: {
    test_a: function(self) {
      //access to object with the "self" object as a parameter
      console.log(self.number);
    },
    test_b: function() {
      console.log(this.number); // ? The problem
    }
  }
};

//----

var myClass = new MyClass(110);
myClass.run();


有什么方法可以访问this对象并具有如下所示的结构?

myClass.events.test_b();
  

我需要这个?,而不必使用我刚刚创建的实例,如下所示:?

myClass.events.test_a(myClass);

3 个答案:

答案 0 :(得分:3)

通常,最好避免以这种方式设计结构。

但是您可以通过在构造函数中绑定events函数来做到这一点,这意味着创建事件对象的“拥有”副本。请参见此最小更改版本中的***条评论:

// NOTE: Sticking to ES5 as the OP seems to be doing that

var MyClass = function(number) {
  this.number = number || 4;
  // *** Bind the functions on `this.events` to `this`
  var self = this;
  var events = self.events;
  self.events = {};
  Object.keys(events).forEach(function(key) {
    if (typeof events[key] === "function") {
      self.events[key] = events[key].bind(self);
    }
  });
};
// I've added the "name" parameter that's being passed around
// so we can be sure that the results for multiple
// instances are correct
MyClass.prototype = {
  constructor: MyClass, // *** Don't break prototype.constructor
  run: function(name) {
    //direct access to object
    console.log(name, "Direct access in object:", this.number);

    //access to object with the "self" object
    var self = this;
    setTimeout(function() {
      console.log(name, "In setTimeout callback:", self.number);
    }, 1000);

    //access to object with the "self" object as a parameter
    this.events.test_a(name, self);

    //here is the problem
    this.events.test_b(name);
  },
  events: {
    test_a: function(name, self) {
      //access to object with the "self" object as a parameter
      console.log(name, "In test_a:", self.number);
    },
    test_b: function(name) {
      console.log(name, "In test_b:", this.number); // ? Not a problem anymore
    }
  }
};

//----

var mc1 = new MyClass(110);
var mc2 = new MyClass(220);
setTimeout(function() {
    mc1.run("mc1");
}, 1000);
setTimeout(function() {
    mc2.run("mc2");
}, 2000);
.as-console-wrapper {
    max-height: 100% !important;
}


旁注:请参阅我添加到要分配给prototype的对象的这一行:

constructor: MyClass, // *** Don't break prototype.constructor

默认情况下,函数上的prototype对象具有指向该函数的constructor属性,因此最好这样做。

答案 1 :(得分:2)

您可以通过以下方式传递<TextField id="standard-full-width" label="Password" style={{ margin: 8 }} fullWidth margin="normal" placeholder="*******" /> 实例的上下文来调用events.test_b

MyClass

this.events.test_b.call(this);

答案 2 :(得分:1)

我建议使用现代JS和箭头功能。

也许还有向下转换的编译器(如有必要)

class MyClass {
  constructor(number = 4) {
    this.number = number;
  }

  run() {
    //direct access to object
    console.log("run", this.number);

    // no need for "self"
    setTimeout(() => {
      console.log("setTimeout", this.number);
    }, 1000);

    //access to object with the "this" object as a parameter
    this.events.test_a(this);

    //here is the problem
    this.events.test_b();
  }

  events = {
    test_a: (self) => {
      //access to object with the "self" object as a parameter
      console.log("test_a", self.number);
    },

    test_b: () => {
      console.log("test_b", this.number); // ? The problem
    }
  }
};

//----

var a = new MyClass(110);
a.run();
console.log("---");

var b = new MyClass(42);
b.run();
console.log("---");

Typescript也可能是替代方案,因为它包含了转译器。

imo。仅仅因为目标受众的一部分仍然使用过时的浏览器并且需要支持它们,所以编写过时的代码是不合理的。是的,我也有使用IE10的客户端,并且需要支持该浏览器。