#javascript #class #methods #constructor
#javascript #класс #методы #конструктор
Вопрос:
В Java вы можете вызывать методы, которые помогут вам выполнить тяжелую работу в конструкторе, но javascript требует, чтобы сначала был определен метод, поэтому мне интересно, есть ли другой способ, которым я мог бы это сделать, или я вынужден вызывать метод, который выполняет тяжелую работу после того, как он был определен. Я предпочитаю сохранять функции экземпляра, содержащиеся в объекте / классе, и мне кажется странным, что мне пришлось бы иметь конструктор в самом конце объекта / класса.
function Polynomials(polyString)
{
// instance variables
this.polys = [];
this.left = undefined;
this.right = undefined;
// This does not work because it's not yet declared
this.parseInit(polyString);
// this parses out a string and initializes this.left and this.right
this.parseInit = function(polyString)
{
//Lots of heavy lifting here (many lines of code)
}
// A lot more instance functions defined down here (even more lines of code)
// Is my only option to call it here?
}
Комментарии:
1. Это связано с подъемом и объявлениями против выражений.
Ответ №1:
Вот что я бы сделал:
var Polynomials = function() {
// let's use a self invoking anonymous function
// so that we can define var / function without polluting namespace
// idea is to build the class then return it, while taking advantage
// of a local scope.
// constructor definition
function Polynomials( value1) (
this.property1 = value1;
instanceCount ;
// here you can use publicMethod1 or parseInit
}
// define all the public methods of your class on its prototype.
Polynomials.prototype = {
publicMethod1 : function() { /* parseInit()... */ },
getInstanceCount : function() ( return instanceCount; }
}
// you can define functions that won't pollute namespace here
// those are functions private to the class (that can't be accessed by inheriting classes)
function parseInit() {
}
// you can define also vars private to the class
// most obvious example is instance count.
var instanceCount = 0;
// return the class-function just bui<
return Polynomials;
}();
Примечания:
Rq 1:
функции-прототипы являются общедоступными методами, доступными для каждого экземпляра класса.
var newInstance = new MyClass();
newInstance.functionDefinedOnPrototype(sameValue);
Rq2:
Если вам нужна действительно «частная» переменная, вы должны получить этот путь:
function Constructor() {
var privateProperty=12;
this.functionUsingPrivateProperty = function() {
// here you can use privateProperrty, it's in scope
}
}
Constructor.prototype = {
// here define public methods that uses only public properties
publicMethod1 : function() {
// here privateProperty cannot be reached, it is out of scope.
}
}
лично я использую только свойства (не частные переменные) и использую «общее соглашение для уведомления о том, что свойство является частным. Таким образом, я могу определить каждый общедоступный метод в прототипе.
После этого любой, кто использует свойство с префиксом «, должен взять на себя ответственность, это кажется справедливым. 🙂
Для разницы между function fn() {}
и var fn= function() {}
, google или S.O. для этого вопроса короткий ответ заключается в том, что function fn() {}
получает определенную функцию и присваивает ее значение во всей области видимости, когда var
определяется переменная, но ее значение вычисляется только тогда, когда код выполнил оценку.
Комментарии:
1. Это похоже на потерянное руководство, которое я искал, у меня все еще есть несколько дополнительных вопросов о области видимости и экземпляре по сравнению со статическими функциями — время, чтобы начать играть и находить некоторые вещи 🙂 Мне действительно нравится, как все организовано и самодостаточно.
2. Да, это очень простой способ продолжения. У меня могут быть другие замечания, если вам интересно.
3. Являются ли прототипированные функции статическими методами? На самом деле это был следующий вопрос, который я собирался задать в stackoverflow
4. Это
function parseInit()
то же самое, чтоvar parseInit = function()
по какой-то причине я чувствую себя более комфортно с var — как будто это модификатор области видимости, поскольку я перехожу из Java / C #, хотя я знаю, что это не так; это то, с чем мне придется смириться.5. @CTS_AE Это почти то же самое. Объявление переменной поднимается в обоих случаях. Однако есть важное отличие: при объявлении функции также поднимается все определение, так что вы можете вызвать функцию до того, как она была определена в коде, но это не относится к выражению функции.
Ответ №2:
Ваши «переменные экземпляра» объявляются в объекте «this», что, если вы ищете эквивалент Java, немного похоже на то, чтобы сделать их общедоступными. Вы можете объявлять переменные с var
ключевым словом, что делает их более похожими на частные переменные в вашей функции конструктора. Затем они подвергаются «подъему», что в основном означает, что они считаются объявленными в верхней части вашей функции (или в любой другой области, в которой они объявлены), даже если вы пишете их после вызывающего кода.
Комментарии:
1. Никогда не знал о подъеме, спасибо за четкое и понятное объяснение.
2. Я не уверен, что это может сработать, потому что я пытаюсь ссылаться на переменные экземпляра в функции parseInit . Я предполагаю, что мне также нужно изменить их на private / var.
3. Ах, тогда вам, возможно, придется выполнить немного странно выглядящее присвоение этого переменной a la
var that = this;
. Затем, когда вы хотите обновитьthis.foo
свою внутреннюю функцию, выthat.foo
вместо этого ссылаетесь на . Это связано с тем, чтоthis
ключевое слово в Java немного странное, поскольку оно будет применяться к области действия внутренней функции, а не к области действия вашей функции конструктора.4. Я помню, что мне пришлось проделать этот небольшой хакерский обходной путь в проекте около 2 лет назад; Я полностью забыл об этом до сих пор, спасибо.
Ответ №3:
Я бы создал объявление функции, а затем присвоил переменную объявлению функции. Причина в том, что JavaScript поднимет ваши объявления функций.
Итак, вы могли бы сделать это:
function Polynomials(polyString) {
// instance variables
this.polys = [];
this.left = undefined;
this.right = undefined;
// this parses out a string and initializes this.left and this.right
this.parseInit = parseInitFunc;
// This does not work because it's not yet declared
this.parseInit(polyString);
// A lot more instance functions defined down here (even more lines of code)
function parseInitFunc(polyString) {
console.log('executed');
}
// Is my only option to call it here?
}
Таким образом, ваш код остается чистым.
Комментарии:
1. Но это все равно не поднимет выражение, поэтому
this.parseInit = fn;
оно все равно не будет определено, и вы не сможете этого сделатьfunction this.parseInit() {...
2. Теперь вы добавили некоторый код, но он точно такой же, как у OP, разницы нет?
3. @adeneo, это требует дополнительной очистки (например, изменения моих комментариев), но он поднимает «функцию parseInitFunc», а затем присваивает this.parseInit, а затем вызывает это, по крайней мере, я считаю, что это должно произойти, я еще не пробовал это, но я никогда не знало «подъеме» до сих пор. Объяснение Rom99 сработало для меня лучше и быстрее, но эта ссылка определенно содержит некоторые глубокие детали 🙂
4. @CTS_AE — Хм, нет! Функция вызывается перед выражением, так что это точно то же самое, это ничего не меняет.
5. Теперь он будет работать с измененным порядком, но он все тот же, что и CTS_AE, упомянутый в вопросе, просто вызов функции после ее определения, конечно, будет работать.