Вход

Просмотр полной версии : Правильное оформление объекта


bFree
25.07.2012, 19:10
Встала необходимость освоить JS на хорошем уровне. Возник вопрос.

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

Вот пример:


// Как начал писать я
function foo(init_params) {
var self = this; // Еще один вопрос: это антипаттерн?

var private_member; // Я вижу приватные свойства так

var init = function(self) {
// конструктор
}

// Публичные методы
self.someMethod = function(params) {
// Метод
}

// --- //
init(self); // вызов конструктора
}

var bar = new foo(params);
bar.someMethod(...);


В чем ужас подобного подхода? Везде, где я смотрю и читаю, я вижу такое:


function foo() {
var privateMember;

this.publicMember = false;
}

foo.prototype.method = function(a) {
// метод
};

var bar = new foo();
b.method(...);


Почему так? Имхо, читабельность ниже.

devote
25.07.2012, 19:14
В чем ужас подобного подхода?
в том что в первый вариант нельзя будет расширить, то-есть унаследовать другим классом, так как все методы будут спрятаны в конструкторе, и получить их через прототип будет не возможно. Второй же вариант дает такую возможность.

bFree
25.07.2012, 19:18
devote,
о, спасибо. Честно говоря я все еще немного запутываюсь в этих прототипах.
Я так понимаю, что foo.prototype - это базовый объект Function? То есть мы добавляем методы к Function() ?

И насчет антипаттерна self = this можете что-либо сказать?

oneguy
25.07.2012, 19:19
var self = this; // Еще один вопрос: это антипаттерн?
Так обычно делают для того, чтобы можно было использовать новосозданный объект внутри функций, определённых внутри конструктора. Если у вас нет таких функций, то и нет смысла так делать, можно внутри конструктора использовать this.

bFree
25.07.2012, 19:22
oneguy,
Я пишу var self = this; для того, чтобы можно было вызывать методы этого класса внтури, например, jQuery.each, т.к. там this переопределяется.

self.someMethod = function() {};

self.someEach = function() {
jQuery.each(domObjects, function(i, obj) {
self.someMethod();
});
}

oneguy
25.07.2012, 19:23
Я так понимаю, что foo.prototype - это базовый объект Function? То есть мы добавляем методы к Function() ?
Нет, каждый раз при создании функции для неё создаётся ещё объект - прямой наследник Object.prototype, и для функции устанавливается свойство prototype на него. Это свойство функции prototype можно изменять, установить на другой объект.

oneguy
25.07.2012, 19:30
Я пишу var self = this; для того, чтобы можно было вызывать методы этого класса внтури, например, jQuery.each, т.к. там this переопределяется.
Правильно. я о том же и говорил. У вас есть функция, объявленная внутри конструктора, которая должна использовать объект, созданный конструктором. Однако есть метод someEach задаёт общее поведение всех объектов класса, то его нужно записать в прототип, как показали ранее.

foo.prototype.someEach = function() {
var self=this;
jQuery.each(domObjects, function(i, obj) {
self.someMethod();
});
};

Вместо var self=this; можно использовать ещё другой подход - с помощью метода Function.prototype.bind.

foo.prototype.someEach = function() {
jQuery.each(domObjects, function(i, obj) {
this.someMethod();
}.bind(this));
};

bFree
25.07.2012, 20:00
oneguy,
Жаль, что так громоздко получается =(
Постоянные bind или self = this в каждом методе почти. Да и читабельность ухудшится, если где-то this в методах, где-то self..

Других способо конструировать объекты нет?

oneguy
26.07.2012, 22:57
oneguy,
Жаль, что так громоздко получается =(
Постоянные bind или self = this в каждом методе почти. Да и читабельность ухудшится, если где-то this в методах, где-то self..

Других способо конструировать объекты нет?
Вообще-то есть, это очень размытый вопрос, но в данном случае я не вижу лучшего решения проблемы, чем через bind или var self = this.

oneguy
26.07.2012, 23:05
foo.prototype.someEach = function() {
jQuery.each(domObjects, function(i, obj) {
this.someMethod();
}.bind(this));
};
Кстати, в этом случае, если в анонимной функции только вызывается один метод, то его необязательно заворачивать в функцию, достаточно только применить bind.
foo.prototype.someEach = function() {
jQuery.each(domObjects, foo.prototype.someMethod.bind(this));
};