Подтвердить что ты не робот

Вложенный класс в javascript, наследование частных методов

Я новичок в 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 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();             
        }   
    }
}();

Кто-нибудь может мне помочь? Я собираюсь разобраться с этим.

Федра.

4b9b3361

Ответ 1

Закрытие - это лексическая функция, а не семантическая. Если объект находится за пределами лексической области действия другого, он больше не может быть "вложенным" и доступ к прежним локальным переменным. В коде вашей вложенной функции/класса нет такой вещи, как this.privateMethod, потому что privateMethod никогда не является свойством MainObject. Это просто локальная переменная внутри функции.

В JavaScript нет таких вещей, как "частные свойства", "частные методы" или "частные члены". Черт, нет такой вещи, как "класс". Некоторым людям нравится подражать частным членам, использующим локальные переменные, как указано выше, но это приводит к таким случаям, когда возникает несоответствие между этими двумя концепциями и укусывает один из них.

В заключение, это плохая идея написать Java-код со всеми его методами OO в JS, так же, как плохой идеей писать 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();​

Ответ 2

Использование соглашения подчёркивания для методов "private" - разумный способ сохранить организованность.

  MainObject = function() {

       this._privateVariable = "i'm private";

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

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

Ответ 3

Хорошо, чтобы обеспечить преимущество прототипного наследования, когда все "подклассы" используют один экземпляр метода в прототипе, но ТАКЖЕ предоставляют функцию наследования частных экземпляров... Я придумал:

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 so is an "instance var"
alert(bob.latentPower); //returns undefined 
alert(buford.latentPower); //returns undefined, so is "private".

Насколько это полезно?

Ответ 4

Классы JavaScript и наследование (ES6)

Согласно ES6, вы можете использовать классы JavaScript и наследование, чтобы выполнить то, что вам нужно.

Классы JavaScript, представленные в ECMAScript 2015, в основном являются синтаксическим сахаром по сравнению с существующим наследованием на основе прототипов JavaScript.

Ссылка: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

Ниже приведены примеры с переменными, но их можно применять и к функциям.


Наследование (1-й подход)

Это решение может использоваться только с геттерами для ваших личных переменных, иначе ваш подкласс не получит к ним доступ.

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"

Ответ 5

Какая система OO позволяет вам наследовать частные методы? Часть частной является недоступной для других объектов.

В JS, в частности, "частные члены" на самом деле являются только локальными переменными функции, в которой они объявлены. JS не имеет типичных понятий OO "class", "inheritance", "public" и "private", поэтому вы не можете ожидать, что скопируйте свои методы ООП с других языков ООП.

Ответ 6

Это соглашение. Вы можете имитировать методы 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'});

Это лучший подход, который я нашел для эмуляции методов Java OO...

Но есть проблема, очень неэффективна... Вместо этого вы должны использовать прототип, потому что иначе он создавал бы один объект для каждой функции на один экземпляр класса.

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, иначе это будет "окно".