Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Правильное оформление объекта (https://javascript.ru/forum/misc/30150-pravilnoe-oformlenie-obekta.html)

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
В чем ужас подобного подхода?

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

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

Цитата:

Сообщение от bFree
Я так понимаю, что foo.prototype - это базовый объект Function? То есть мы добавляем методы к Function() ?

Нет, каждый раз при создании функции для неё создаётся ещё объект - прямой наследник Object.prototype, и для функции устанавливается свойство prototype на него. Это свойство функции prototype можно изменять, установить на другой объект.

oneguy 25.07.2012 19:30

Цитата:

Сообщение от bFree
Я пишу 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

Цитата:

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

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

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

oneguy 26.07.2012 23:05

Цитата:

Сообщение от oneguy
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));
};


Часовой пояс GMT +3, время: 10:17.