Javascript javascript中的嵌套类,私有方法的继承

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2286987/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-22 23:37:19  来源:igfitidea点击:

Nested class in javascript, inheritance of private methods

javascriptclassnestedprivate

提问by Phaedra

i'm quite a newbie in javascript, and i'm spending some time trying to create namespaced objects in js.

我是 javascript 的新手,我花了一些时间尝试在 js 中创建命名空间对象。

Now, that's what i'm trying to do:

现在,这就是我想要做的:

MainObject = function() {

    var privateVariable = "i'm private";

    var privateMethod = function() {
        // doSomething
    }

    this.publicMethod = function() {
        // doPublicSomething
    }
}

MainObject.prototype.nested = function() {

    this.publicNestedMethod = function() {

        // that's not working at all
        this.privateMethod(privateVariable);

    }
}

MyObject = new MainObject();

MyObject.publicMethod();
MyObject.publicNestedMethod();

I tried to include the nested class inside the first one, but it's not working also if i try:

我试图将嵌套类包含在第一个类中,但如果我尝试,它也不起作用:

this.nested = function() {

    var mainObject = this;

    return {
        publicNestedMethod = function() {
            mainObject.privateMethod();             
        }   
    }
}();

Someone can help me please? i'm gonna loose my mind on this.

有人可以帮助我吗?我会在这件事上失去理智。

Phaedra.

斐德拉。

回答by Max Shawabkeh

Closures are a lexical feature, not a semantic one. If the object is outside the lexical scope of another, it can no longer be "nested" and access the former's local variables. In the code of your nested function/class, there's no such thing as this.privateMethod, because privateMethodis nevermade to be a property of MainObject. It's simply a local variable inside a function.

闭包是一种词汇特征,而不是语义特征。如果对象在另一个的词法范围之外,它就不能再“嵌套”并访问前者的局部变量。在你的嵌套函数/类的代码,有没有这样的东西this.privateMethod,因为privateMethod从来没有做成的属性MainObject。它只是一个函数内部的局部变量。

There's no such things as "private properties", "private methods" or "private members" in JavaScript. Hell, there's no such thing as a "class". Some people like to emulate private members using local variables as above, but doing so results in cases like this, where the discrepancy between the two concepts comes and bites one in the behind.

JavaScript 中没有“私有属性”、“私有方法”或“私有成员”之类的东西。天哪,没有“班级”这样的东西。有些人喜欢像上面一样使用局部变量来模拟私有成员,但这样做会导致这样的情况,两个概念之间的差异出现并在后面咬了一口。

To conclude, it is a bad idea to write Java code, with all its OO techniques in JS, just as it is a bad idea to write C code, with all its pointers and unbounded buffers, in C#. Sure, in both cases you can do it, but you would be failing to appreciate and exploit the language's features this way.

总而言之,在 JS 中使用所有面向对象技术编写 Java 代码是一个坏主意,就像在 C# 中编写包含所有指针和无限缓冲区的 C 代码也是一个坏主意。当然,在这两种情况下您都可以做到,但是您将无法以这种方式欣赏和利用该语言的功能。

And now that I'm done with the rant, you can do something like this to get "namespaced" functions:

现在我已经完成了咆哮,你可以做这样的事情来获得“命名空间”函数:

MainObject = function() {
    var privateVariable = "I'm private";

    var privateMethod = function() {
        alert('Private');
    }

    this.publicMethod = function() {
        alert('Public');
    }

    this.nested = {
      publicNestedMethod: function() {
        privateMethod();
      }
    };

    // or

    this.nested = (function() {
      var nestedPrivate = 5;

      return {
        publicNestedMethod: function() {
          alert(nestedPrivate);
          privateMethod();
        }
      };
    })();
}

MyObject = new MainObject();

MyObject.publicMethod();
MyObject.nested.publicNestedMethod();?

回答by morgancodes

Using the convention of underscore for "private" methods is a reasonable way to keep things organized.

将下划线约定用于“私有”方法是保持组织有序的合理方式。

  MainObject = function() {

       this._privateVariable = "i'm private";

       this._privateMethod = function() {
          // doSomething
       }

        this.publicMethod = function() {
          // doPublicSomething
        }
}

回答by Brett

Well to provide the benefit of prototypal inheritance where all "subclasses" share a single instance of the method in prototype, but to ALSO provide the feature of inheriting private instances... I came up with:

那么提供原型继承的好处,其中所有“子类”共享原型中方法的单个实例,但还提供继承私有实例的功能......我想出了:

function Person(name,latentPower){
    var privatesForChildren =   { password:"xyz"
                                 ,latentPower:"invisibility"}
    this.inherit = function(){
        for(v in privatesForChildren){
            eval("var " + v + "=privatesForChildren['" + v + "'];");
        }
    }
    this.name = name;
    this.revealName = function(){ alert("My name is" + this.name + "."); }  
    this.revealPowers = function(){ alert("I'm normal."); } 
}       
function Mutant(name,latentPower,fuel){
    this.inherit.call(this);   // Inherit private instance variables
    var fuel = fuel;
    this.name = name;
    this.revealPowers = function(){
    alert("I manifest the powers of " + latentPower + " when I " + fuel + ".");
    }
}
Mutant.prototype = new Person;
Mutant.prototype.constructor = Mutant;

bob = new Person("Bob","telekenesis");
jim = new Mutant("Jim","nausea","eat pizza");
buford = new Mutant("Buford","Teflon Man","breathe");

jim.revealName(); //Inherited properly from prototype
bob.revealPowers();
jim.revealPowers();
buford.revealPowers();  //distinct from Jim's so is an "instance var"
alert(bob.latentPower); //returns undefined 
alert(buford.latentPower); //returns undefined, so is "private".

How useful is that?

那有多大用处?

回答by Daniel Possamai

JavaScript Classes and Inheritance (ES6)

JavaScript 类和继承 (ES6)

According to ES6, you can use JavaScript classes and inheritance to accomplish what you need.

根据 ES6,您可以使用 JavaScript 类和继承来完成您需要的工作。

JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance.

ECMAScript 2015 中引入的 JavaScript 类主要是 JavaScript 现有的基于原型的继承的语法糖。

Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

参考:https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

I'm showing the examples below with variables, but it can be applied also to functions.

我用变量展示了下面的例子,但它也可以应用于函数



Inheritance (1st Approach)

继承(第一种方法)

This solution can only be used with getters for your private variables, otherwise your subclass will not get access to them.

此解决方案只能与私有变量的 getter 一起使用,否则您的子类将无法访问它们。

class Main {
  constructor() {
    let privateVariable = "private";
    this.publicVariable = "public";

    this.getPrivateVariable = () => {
      return privateVariable;
    }
  }
}

Main.Sub = class Sub extends Main {
  getAllVariables() {
    return this.publicVariable + "-" + this.getPrivateVariable();
  }
}

// Testing...

let main = new Main();
let sub = new Main.Sub();

console.log(main.privateVariable); // undefined
console.log(main.publicVariable); // "public"

console.log(sub.privateVariable); // undefined
console.log(sub.publicVariable); // "public"

console.log(main.getPrivateVariable()); // "private"
console.log(sub.getPrivateVariable()); // "private"
console.log(sub.getAllVariables()) // "public-private"

Nesting (2nd Approach)

嵌套(第二种方法)

Maybe this solution is better for you because it doesn't expose your private variables outside the Main and Nested classes.

也许这个解决方案对你更好,因为它不会在 Main 和 Nested 类之外公开你的私有变量。

class Main {
  constructor() {
    let privateVariable = "private";
    this.publicVariable = "public";
    
    Main.Nested = class Nested extends Main {
      getAllVariables() {
        return this.publicVariable + "-" + privateVariable;
      }
    }
  }
}

// Testing...

let main = new Main();
let nested = new Main.Nested();

console.log(main.privateVariable); // undefined
console.log(main.publicVariable); // "public"

console.log(nested.privateVariable); // undefined
console.log(nested.publicVariable); // "public"

console.log(main.getPrivateVariable); // undefined
console.log(nested.getPrivateVariable); // undefined
console.log(nested.getAllVariables()) // "public-private"

回答by mpccolorado

It is a convention. You can imitate OO Java techniques like private members but that's not recommended. You can imitate in this way:

这是一个约定。您可以模仿私有成员之类的 OO Java 技术,但不建议这样做。你可以这样模仿:

MyFunction = function(options){
   var private = {};
   //to reference MyFunction as a context
   var that = this;

   function privateFunctionThatCallPublicMethod(){
      that.publicFunction("hello");
   }

   this.publicFunction = function(params){
      alert(params + "  " + private);  
   }
   ...
}

var instance = new MyFunction({oneOption:'fsdfsad'});

This is the bests approach i found to emulate OO Java Techniques...

这是我发现的模拟 OO Java 技术的最佳方法......

But there is a problem, is very inefficient... You must use prototype instead, because otherwise it would create one object per function per instance of the "class".

但是有一个问题,效率非常低……您必须改用原型,否则它将为每个“类”实例的每个函数创建一个对象。

MyFunction = function(options){
   this._private = {};
}

MyFunction.prototype._privateFunctionThatCallPublicMethod = function(){
   this.publicFunction("hello");
}

MyFunction.prototype.publicFunction = function(params){
   alert(params + "  " + this._private);  
}

Like you think private members are(in this way) a convention. Also, there is another thing you must know...

就像您认为私人成员(以这种方式)是约定一样。另外,还有一件事你必须知道......

When you pass a function of an object as a parameter to another function you must bind the context of the function...

当您将对象的函数作为参数传递给另一个函数时,您必须绑定该函数的上下文...

function bind(fnThis, fn) {
  return function(){
    return fn.apply(fnThis, arguments);
  };
}

function makeSomething(callback){
  callback("hello");
}

var instance = new MyFunction();
makeSomething(bind(instance, instance.publicFunction));

This is because you must bind "this" as instance in the body of the publicFunction, otherwise is gonna be "window" instead.

这是因为您必须将“this”绑定为 publicFunction 主体中的实例,否则将改为“window”。

回答by Gabe

What OO system lets you inherit private methods? Part of being private is being unaccessible from other objects.

什么 OO 系统允许您继承私有方法?私有的一部分是其他对象无法访问。

In JS in particular, "private members" are really just local variables of the function where they are declared. JS doesn't have typical OO notions of "class", "inheritance", "public", and "private", so you can't expect to copy your OOP techniques verbatim from other OOP languages.

特别是在 JS 中,“私有成员”实际上只是声明它们的函数的局部变量。JS 没有典型的“类”、“继承”、“公共”和“私有”的 OO 概念,因此您不能期望从其他 OOP 语言中逐字复制您的 OOP 技术。