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

问题描述 投票:12回答:6

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

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

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

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

this.nested = function() {

    var mainObject = this;

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

有人可以帮帮我吗?我会对此失去理智。

淮德拉。

javascript class nested private
6个回答
14
投票

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

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

总而言之,用JS中的所有OO技术编写Java代码是一个坏主意,就像用C#编写C代码及其所有指针和无界缓冲区一样。当然,在这两种情况下你都可以做到,但你不会以这种方式欣赏和利用语言的功能。

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

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

6
投票

对“私人”方法使用下划线约定是保持组织有序的合理方法。

  MainObject = function() {

       this._privateVariable = "i'm private";

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

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

4
投票

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

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".

这有用吗?


1
投票

JavaScript Classes and Inheritance (ES6)

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

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

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

我将使用变量显示以下示例,但它也可以应用于函数。


继承(第一种方法)

此解决方案只能与您的私有变量的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"

嵌套(第二种方法)

也许这个解决方案对你更好,因为它不会在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"

0
投票

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

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


0
投票

这是一个惯例。您可以模仿私有成员之类的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'});

这是我发现仿效OO Java技术的最佳方法......

但是有一个问题,效率很低......你必须使用原型,否则它会为每个“类”实例的每个函数创建一个对象。

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

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

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

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

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

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”作为实例绑定在publicFunction的主体中,否则将成为“窗口”。

© www.soinside.com 2019 - 2024. All rights reserved.