Самый оптимизированный способ создания JS Object - PullRequest
3 голосов
/ 01 января 2012

Я ищу наиболее оптимизированный способ иметь объект в JS;поскольку JS позволяет вам делать что-то несколькими способами, я хочу знать, что считается «наилучшей практикой».

Концептуальное использование объекта будет следующим:

var John = new Person('John');
var Foo = new Person('Foo');

console.log(John.getName()); //Return 'John'
console.log(Foo.getName()); //Return 'Foo'
console.log(John.name); //undefined
console.log(Foo.name); //undefined

IВот несколько примеров:

Пример # 1:

var Person = function (name) {
    this.getName = function () { return name; }
}

Здесь у меня фактически нет свойств;«имя» не может быть изменено или прочитано public, а метод getName может быть доступен public и вызываться с локальной переменной name.Это на самом деле отвечает моим потребностям.

Пример # 2:

function Person (name) {
    this.getName = function () { return name; }
}

Это поведение аналогично примеру № 1.Я просто не уверен в разнице между var method = function () {}; и function method() {}; с точки зрения функциональности и производительности.

Пример # 3:

var Person = function (name) {
    this.name = name;    
    Person.prototype.getName = function () { return this.name; }
}

Здесь у меня есть свойство name, которое можетбыть открытым для чтения / записи, и у меня также есть прототип метода getName, к которому можно получить доступ public.

Пример # 4:

var Person = function (name) {
    this.name = name;
    if (!Person._prototyped) {
        Person.prototype.getName = function () { return this.name; }
        Person._prototyped = true;
    }
}

Здесь у меня есть то, что у меня было в примере # 3 сразница в том, что я проверяю, что методы-прототипы устанавливаются только один раз и только тогда, когда это необходимо.

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

Ответы [ 3 ]

3 голосов
/ 01 января 2012

Для того, что вы хотите, лучший способ, вероятно, это:

/**
 * @constructor
 */
function Person(name) {
    this.getName = function() {
        return name;
    };
}

Почему это? Ну, во-первых, инкапсуляция. Если возможно, вы обычно хотите поместить функцию в прототип, например, так:

/**
 * @constructor
 */
function Person(name) {
    this.name = name;
}

Person.prototype.getName = function() {
    return this.name;
};

Однако! В этом случае оказывается, что вы не хотите, чтобы Person.name был доступен. По этой причине вам нужно использовать замыкания.

Что касается этого метода:

var Person = function (name) {
    this.name = name;    
    Person.prototype.getName = function () { return this.name; }
}

Это не хорошо. Вы публично выставляете this.name, поэтому он не дает никаких преимуществ по сравнению с предыдущим методом-прототипом, но вы постоянно перезаписываете Person.prototype.getName одной и той же функцией. Там нет смысла делать это; this будет подходящим объектом каждый раз. Более того, Person.prototype.getName не будет доступен, пока не будет создан первый объект Person, поэтому нет особого смысла делать его "публичным" в первую очередь. Ваш четвертый пример в основном идентичен, с большим количеством глупостей, которые труднее понять, но у него все еще есть все недостатки.

Итак, в этом случае перейдите к первой версии; однако, когда это возможно, установите методы на prototype, чтобы их можно было вызывать вне экземпляра.

Наконец, я бы порекомендовал использовать:

function Person() {
}

над

var Person = function() {
}

потому что 1) во втором примере пропущена точка с запятой, 2) var подразумевает, что конструктор является переменной, которой не должно быть, и 3) я не верю, что JDoc позволяет применять к нему @constructor , вызывая предупреждение в Closure Compiler как минимум 1 .


1 Хорошо, не так важно. Но все же ...

2 голосов
/ 01 января 2012

В примерах 3 и 4 оно должно быть:

var Person = function (name) {
    this.name = name;    
};
Person.prototype.getName = function () { return this.name; }

И

var Person = function (name) {
    this.name = name;
};

if (!Person._prototyped) {
    Person.prototype.getName = function () { return this.name; }
    Person._prototyped = true;
}

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

Не уверен, какой из них самый быстрый (поскольку все они действительны для ваших целей), о чем вы и просите, но я не стал бы беспокоиться, так как это похоже на микрооптимизацию. Если вы должны знать, то вы можете использовать сайт, как http://jsperf.com/

Самый быстрый способ, которым я могу представить, был бы:

function Person(name) {
    this.getName = function() {
        return name;
    };
}

Как сказал Минитек. Причина в следующем:

Каждый раз, когда движок js «поднимается» по цепочке прототипов, он отнимает долю мс (или долю секунды в IE :)), а объявление переменных может занимать время (также незначительное). избегайте этого тоже. Надеюсь, что это поможет

0 голосов
/ 01 января 2012

Хорошо работает на node.js.AFAIK, аргументы изменчивы.Закрытия будут помнить значения.Следовательно, это будет работать.Я думаю, это решает все это.

var Person = function(Name) {
    this.getName = function(){return Name;}
    this.setName = function(newName)  { Name = newName; }
},

me  = new Person('John');
console.log(me.getName());
me.setName('Peter');
console.log(me.getName());
...