简体   繁体   English

JS嵌套原型访问父节点

[英]JS nested prototype access parent node

According to following code, I have a small problem with accessing this variable in prototypes. 根据以下代码,在原型中访问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(); 


Is there any way to access the this object and having some structure like following? 有什么方法可以访问this对象并具有如下所示的结构?

myClass.events.test_b();

I need this👆 without using the instance that I've just created like following:👇 我需要这个👆而无需使用我刚刚创建的实例,如下所示:👇

myClass.events.test_a(myClass);

In general, you're best off avoiding designing the structure that way. 通常,最好避免采用这种方式设计结构。

But you can do it by binding the events functions in the constructor, which means creating an "own" copy of the events object. 但是您可以通过在构造函数中绑定events函数来做到这一点,这意味着创建事件对象的“自己”副本。 See *** comments in this minimal-changes version: 请参阅此最小更改版本中的***注释:

 // 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; } 


Side note: See this line I added to the object you're assigning to prototype : 旁注:请参阅我添加到要分配给prototype的对象的这一行:

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

By default, the prototype object on a function has a constructor property pointing back to the function, so best to do that. 默认情况下,函数上的prototype对象具有指向该函数的constructor属性,因此最好这样做。

You can call events.test_b passing the context of MyClass instance as follows: 您可以events.test_b通过传递MyClass实例的上下文来调用events.test_b

this.events.test_b.call(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.call(this); }, 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(); 

I'd recommend using modern JS and arrow functions. 我建议使用现代JS和箭头功能。

And maybe a transpiler for downward compatibility (if necessary) 也许是向下转换的编译器(如有必要)

 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 may also be an alternative, as it includes the transpiler. 打字稿也可能是替代方案,因为它包括翻译器。

imo. imo。 it is unreasonable to write outdated code, just because a part of your target audiance still uses outdated browsers and you need to support them. 仅仅因为目标受众的一部分仍然使用过时的浏览器并且需要支持它们,所以编写过时的代码是不合理的。 And yes, I have clients with IE10 too and need to support down to that browser. 是的,我也有使用IE10的客户端,并且需要支持该浏览器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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