JavaScript “классы”

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

Если это работает вообще, результат неизбежно будет ужасным.

8
задан cdmckay 25 July 2009 в 03:20
поделиться

4 ответа

То, что вы делаете в своем примере, не является шаблоном «класса», о котором люди думают в JS - обычно люди думают о более «нормальной» модели классов Java / C # / C ++ / и т. Д., Которые можно подделать с помощью библиотек.

Вместо этого ваш пример на самом деле довольно нормальный и хороший JS-дизайн, но для полноты я рассмотрю различия в поведении, которые вы увидите между частными и общедоступными «членами», которые у вас есть

var private = "a private variable";
this.public = "a public variable";

Доступ к private из любой из ваших функций будет намного быстрее, чем доступ к public , потому что местоположение private может быть достаточно хорошо определено просто с помощью статического поиск движком JS. Попытки получить доступ к общедоступным требуют поиска, большинство современных JS-движков выполняют определенную степень кэширования поиска, но это по-прежнему дороже, чем простой доступ к переменным с ограниченной областью видимости.

var privatefn = function() { ... };
this.publicfn = function() { ... };

К этим функциям применяются те же правила поиска, что и для доступа к указанным выше переменным, единственная реальная разница (в вашем примере) состоит в том, что если ваши функции вызываются, скажем, privatefn () vs this.publicfn () , privatefn всегда будет получать глобальный объект для this . Но также, если кто-то делает

f = foo.publicfn;
f();

, тогда вызов f будет иметь глобальный объект как this , но он сможет изменить частный переменная.

Однако более нормальным способом выполнения общедоступных функций (который решает проблему с отключенной общедоступной функцией, изменяющей частные члены) является размещение общедоступных функций в прототипе, например.

14
ответ дан 5 December 2019 в 07:59
поделиться

Пока это хорошо, но есть еще один уровень доступа, который вы упустили.

this.publicfn - действительно привилегированный метод, поскольку он имеет доступ к закрытым членам и функциям.

Чтобы добавить методы, которые являются общедоступными, но не привилегированными, измените prototype следующим образом:

FooClass.prototype.reallypublicfn = function () { ... };

обратите внимание, что этот метод не имеет доступа к закрытым членам FooClass, но доступен через любой экземпляр FooClass.

Другой способ добиться этого - вернуть эти методы из конструктора

var FooClass = function()
{
  var private = "a private variable";
  this.public = "a public variable";

  var privatefn = function() { ... };
  this.publicfn = function() { ... };

  return {
    reallypublicfn: function () { ...}
  }
};

var foo = new FooClass();
foo.public = "bar";
foo.publicfn();

В основном, Эти методы сокрытия данных помогут вам придерживаться традиционных методов ООП. Вообще говоря, улучшение сокрытия и инкапсуляции данных в ваших классах - это хорошо.

3
ответ дан 5 December 2019 в 07:59
поделиться

Основным недостатком является то, что вы получите копию publicfn для каждого экземпляра FooClass. Если вы будете создавать много объектов FooClass, было бы более эффективно write

FooClass.prototype.publicfn = function() { ... };
3
ответ дан 5 December 2019 в 07:59
поделиться

Это зависит от ваших потребностей и относительной производительности. Javascript - не самый типобезопасный язык и не очень силен в отношении видимости участников. Традиционно вы можете иметь "частную", "публичную привилегированную" и "публичную" видимость в типе Javascript.

Вы можете объявить частные и общедоступные привилегированные члены, используя:

function FooClass()
{
    var privateVar = 1;
    function privateFn() 
    {
        return privateVar; // etc...
    }
    this.publicVar = 2;
    this.publicFn = function()
    {
       return privateFn();
    }
}

В этом примере используется закрытие функции, которое состоит из объявление функции, которое включает значения из области, в которой определена функция. Это приемлемо, когда видимость элементов необходима, но может привести к накладным расходам. Интерпретатор JavaScript не может повторно использовать определения privateFn или publicFn для каждого экземпляра, поскольку они относятся к переменным или функциям во внешней области. В результате каждый экземпляр FooClass приводит к дополнительному пространству для хранения privateFn и publicFn. Если тип используется нечасто или умеренно, снижением производительности можно пренебречь. Если этот тип используется на странице очень часто или если страница больше соответствует стилю «AJAX», когда память освобождается не так часто, поскольку страница не выгружается, штраф может быть более заметным.

Альтернатива подход заключается в использовании членов-прототипов. Это непривилегированные публичные члены. Поскольку Javascript не является полностью типобезопасным и относительно легко модифицируется после загрузки, безопасность типов и видимость членов не так надежны для управления доступом к внутренним компонентам типов. По соображениям производительности некоторые платформы, такие как ASP.NET Ajax, вместо этого используют именование членов для определения правил видимости. Например, однотипный в ASP. NET Ajax может выглядеть так:

function FooClass2()
{
    this._privateVar = 1;
    this.publicVar = 2;
}
FooClass2.prototype = 
{
    _privateFn : function() 
    { 
        return this._privateVar; 
    },
    publicFn : function() 
    {
        return this._privateFn(); 
    }
}
FooClass2.registerClass("FooClass2");

В этом случае частные члены с ограниченной областью видимости являются частными только по имени, при этом префикс «_» считается частной переменной-членом. У него есть обратная сторона, которая не позволяет члену быть действительно закрытым, но положительная сторона позволяет исправлять объект в памяти. Другое главное преимущество состоит в том, что все функции создаются один раз интерпретатором и движком и повторно используются для типа. Ключевое слово this затем относится к экземпляру типа, даже если сама ссылка на функцию такая же.

Один из способов увидеть разницу в действии - попробовать это с обоими типами (если у вас нет ASP. NET Ajax, вы можете игнорировать последнюю строку в FooClass2, которая вызывает registerClass ())

var fooA = new FooClass(), fooB = new FooClass();
alert(fooA.publicFn===fooB.publicFn); // false

var foo2A = new FooClass2(), foo2B = new FooClass2();
alert(foo2A.publicFn===foo2B.publicFn); // true

Так что это вопрос безопасности типов и видимости членов vs.

1
ответ дан 5 December 2019 в 07:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: