简体   繁体   English

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

[英]Nested class in javascript, inheritance of private methods

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. 淮德拉。

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 privateMethod is never made to be a property of MainObject . 在嵌套函数/类的代码中,没有this.privateMethod这样的东西,因为privateMethod 永远不会成为MainObject的属性。 It's simply a local variable inside a function. 它只是函数内的局部变量。

There's no such things as "private properties", "private methods" or "private members" in JavaScript. 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. 有些人喜欢使用如上所述的局部变量来模拟私有成员,但这样做会导致这样的情况,两个概念之间的差异就会出现并在后面咬一个。

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#. 总而言之,用JS中的所有OO技术编写Java代码是一个坏主意,就像用C#编写C代码及其所有指针和无界缓冲区一样。 Sure, in both cases you can do it, but you would be failing to appreciate and exploit the language's features this way. 当然,在这两种情况下你都可以做到,但你不会以这种方式欣赏和利用语言的功能。

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();​

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

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? 这有用吗?

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" 

What OO system lets you inherit private methods? 什么OO系统允许您继承私有方法? Part of being private is being unaccessible from other objects. 私有的一部分是其他对象无法访问的。

In JS in particular, "private members" are really just local variables of the function where they are declared. 特别是在JS中,“私有成员”实际上只是声明它们的函数的局部变量。 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没有“类”,“继承”,“公共”和“私有”的典型OO概念,因此您不能指望从其他OOP语言逐字复制您的OOP技术。

It is a convention. 这是一个惯例。 You can imitate OO Java techniques like private members but that's not recommended. 您可以模仿私有成员之类的OO Java技术,但不建议这样做。 You can imitate in this way: 你可以这样模仿:

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的主体中,否则将成为“窗口”。

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

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