Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Паттерны и приемы! (https://javascript.ru/forum/misc/24396-patterny-i-priemy.html)

Livaanderiamarum 28.12.2011 14:57

Паттерны и приемы!
 
Общеизвестный прием запаковывания данных в скоп:

(function(){
  var cache = {};
  
  this.nya = function nya (str){
    cache = {}
  };
})();


создастся функция НЯ и в ней доступен cache , из вне он не доступен.

Какие приемы запаковывания, заворачивания вы еще знаете?) Какие еще прикольные приемы знаете, например как ускорить код и.т.п. Давайте обменяемся опытом)

melky 28.12.2011 15:29

прочитай книгу Javascript Patterns от Стояна Стефанова.

пара примеров кода "запаковки"

window.nya = new function(){
    var cache = {};
    this.getCache = function(){
        return cache;
    };
};


вот этот меня поразил, когда я его увидел в первый раз :
({
    css : function(el, prop){
        /*return css-prop*/
    },
    ajax : function(options){
        /*make ajax-request*/
    },
    init : function(name){
        var cache = {};
        this.getCache = function(){ return cache };

        delete this.init;
        window[name] = this;
    }
}).init("myToolbox");

myToolbox.ajax({ url : "foo", async : true }); //ajax-req.
myToolBox.css(document.body, "width"); // some width
myToolbox.getCache(); // {}
typeof myToolbox.cache // undefined.
typeof myToolbox.init // undefined.

Livaanderiamarum 28.12.2011 15:34

window.nya = new function(){
    var cache = {};
    this.getCache = function(){
        return cache;
    };
};


вот тут не понял, чем отличается cache от getCache ? какая разница чем GO засирать? можешь наглядный пример кинуть с этим?

melky 28.12.2011 15:49

window.nya = new function(){
    var cache = {};
    this.getCache = function(){
        return cache;
    };
};

alert([ typeof nya.getCache(), typeof nya.cache, typeof cache ]); // obj, undef, undef.

Livaanderiamarum 28.12.2011 15:54

Цитата:

Сообщение от melky (Сообщение 146835)
window.nya = new function(){
    var cache = {};
    this.getCache = function(){
        return cache;
    };
};

alert([ typeof nya.getCache(), typeof nya.cache, typeof cache ]); // obj, undef, undef.

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

GuardCat 28.12.2011 15:54

Цитата:

Сообщение от melky
вот этот меня поразил, когда я его увидел в первый раз :

Это интересно! Практический эффект тот же, что и от первого варианта, но интереснее.

melky 28.12.2011 15:57

Цитата:

Сообщение от GuardCat (Сообщение 146838)
Это интересно! Практический эффект тот же, что и от первого варианта, но интереснее.

и код понятнее, если кол-во функций типа ajax и css увеличить.

единственная загвоздка - в методе init :)

GuardCat 28.12.2011 15:59

Цитата:

Сообщение от melky
и код понятнее, если кол-во функций типа ajax и css увеличить.

Да, тоже об этом подумал.
Цитата:

Сообщение от melky
единственная загвоздка - в методе init

А в чём загвоздка? Свойство-камикадзе не есть хорошо?

Livaanderiamarum 28.12.2011 16:01

Цитата:

Сообщение от GuardCat (Сообщение 146840)
А в чём загвоздка? Свойство-камикадзе не есть хорошо?

Вообще-то, это ЕСТЬ хорошо)! нахрена нам инициализировать объект несколько раз? наоборот, инициализировали - убрали инициализатор чтобы не засорял

B@rmaley.e><e 28.12.2011 16:16

Цитата:

Сообщение от GuardCat
Свойство-камикадзе не есть хорошо?

+1
Зачем создавать метод, который будет вызван всего один раз (а потом ещё и самоликвидируется)? Лучше сразу сделать анонимную функцию, которая будет собирать и возвращать объект.

Livaanderiamarum 28.12.2011 16:18

Цитата:

Сообщение от B@rmaley.e><e (Сообщение 146845)
+1
Зачем создавать метод, который будет вызван всего один раз (а потом ещё и самоликвидируется)? Лучше сразу сделать анонимную функцию, которая будет собирать и возвращать объект.

покажи твою версию реализации этого примера

B@rmaley.e><e 28.12.2011 16:26

myToolbox = (function () {
	var o = {
		css: function (el, prop) { /*return css-prop*/
		},
		ajax: function (options) { /*make ajax-request*/
		}
	};
	var cache = {};
	o.getCache = function () {
		return cache
	};
	return o;
})();

myToolbox.ajax({
	url: "foo",
	async: true
}); //ajax-req.
myToolBox.css(document.body, "width"); // some width
myToolbox.getCache(); // {}
typeof myToolbox.cache // undefined.

GuardCat 28.12.2011 17:26

А «o» несёт какую-нибудь смысловую нагрузку? Или можно делать так:
myToolbox = (
	function () {
		var cache = {};
		return {
			css: function (el, prop) { 
				/*return css-prop*/
			},
			ajax: function (options) { 
				/*make ajax-request*/
			},
			getCache: function () {
				return cache
			}
		};
	}
)();

?
Мне так читать проще.

melky 28.12.2011 17:41

B@rmaley.e><e так код труднее читать (минимум, только мне). когда функции приведены похожим списком, они как-то легче усваиваются. плюс, неужели так тяжела инициализация и удаление свойства у объекта?

минусом объекта с инициализатором является, конечно, плохая его усваиваемость, если программист не понимает, с чем имеет дело. потом идёт все как по маслу.

и ещё один минусом будет использование одной "приватной" переменной несколькими функциями. для этого инициализирующийся объект не предназначен, а вот анонимная исполняющаяся функция - как раз для этого подходит!

GuardCat, приведённая вами одноразовая фабрика объектов - золотая середина между самоисполняющейся функцией и самоинициализирующемся объектом. )

Livaanderiamarum 28.12.2011 17:46

Цитата:

Сообщение от melky
так код труднее читать (минимум, только мне). когда функции приведены похожим списком, они как-то легче усваиваются. плюс, неужели так тяжела инициализация и удаление свойства у объекта?

+1

Livaanderiamarum 28.12.2011 18:00

Цитата:

Сообщение от melky (Сообщение 146870)
пиши в одно сообщение.
это то же самое, что и вариант GuardCat.

удали свое сообщение я удалил вопрос "чем код лучше"

B@rmaley.e><e 28.12.2011 19:18

Цитата:

Сообщение от Livaanderiamarum
чем твой код лучше?

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

Сообщение от GuardCat
А «o» несёт какую-нибудь смысловую нагрузку?

В моём примере — нет. Оно написано так только для сохранения исходного стиля.
Цитата:

Сообщение от melky
B@rmaley.e><e так код труднее читать (минимум, только мне).

А увидев код вроде
var a = ({
 // сотни тысяч строк кода
Чем, Вы подумаете, будет a? Особенно если Вы программируете на JS пару месяцев и ещё не прочитали JavaScript Patterns Стефанова? Если (function () стало более-менее стандартным синтаксисом (и то постоянно появляются вопросы в духе "Что значит (function () {})") для самовызвающихся функций, то ({ … }) не столь сильно распространено (Хотелось бы увидеть примеры его использования в каких-нибудь приличных библиотеках или JS приложениях).

Далее: IDE. Если среда и догадается каким-нибудь образом о структуре создаваемого объекта (очевидно не в исходном случае, т.к. там понять, куда будет записан объект, без анализа графа потока управления вряд ли получится). А уж догадаться о том, что метод в любом случае будет удалён и, как результат, его не нужно подставлять в какой-нибудь автокомплит, ещё труднее.
Цитата:

Сообщение от melky
неужели так тяжела инициализация и удаление свойства у объекта?

Проблема не в их легкости / тяжёлости, а в том, что непонятно, зачем их объявлять вместе с объектом, если они не будут частью него. Если бы этот метод назывался clone и делал то, что должен делать исходя из названия, вопросов бы не было. Получился бы такой объект-прототип, копию которого всегда можно получить.

melky 28.12.2011 19:40

Цитата:

Сообщение от B@rmaley.e><e (Сообщение 146901)
А увидев код вроде
var a = ({
 // сотни тысяч строк кода
Чем, Вы подумаете, будет a?

ваш пример некорректен. инициализирующая функция не возвращает результат. она только удаляет себя и инкапсулирует создаёт переменную в глобальной области.

Цитата:

Сообщение от B@rmaley.e><e (Сообщение 146901)
Особенно если Вы программируете на JS пару месяцев и ещё не прочитали JavaScript Patterns Стефанова?

с этим проблема, да. но это я уже расписал в своём сообщении выше.


Цитата:

Сообщение от B@rmaley.e><e (Сообщение 146901)
(Хотелось бы увидеть примеры его использования в каких-нибудь приличных библиотеках или JS приложениях).

oops... с этим проблема.

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

Цитата:

Сообщение от B@rmaley.e><e (Сообщение 146901)
Далее: IDE. Если среда и догадается каким-нибудь образом о структуре создаваемого объекта (очевидно не в исходном случае, т.к. там понять, куда будет записан объект, без анализа графа потока управления вряд ли получится).

хм. т.е. вы хотите сказать, что IDE не поймёт кода и не подставит заверщение имени переменной в этом случае ?

a = {
    test : "nice",
    magic : function(){
        return this.te*!*<CTRL+SPACE>*/!*
    }
};


PS Komodo Edit, как помню, всё отлично понимал. это было год назад.

B@rmaley.e><e 28.12.2011 19:56

Цитата:

Сообщение от melky
она только удаляет себя и инкапсулирует создаёт переменную в глобальной области.

Этот подход тем более плох. Не надо решать за пользователя, куда записывать объект.
Цитата:

Сообщение от melky
вы хотите сказать, что IDE не поймёт кода и не подставит заверщение имени переменной в этом случае ?

Да. Возьмите свой исходный код, добавьте его в проект, а в соседнем файле наберите myToolbox.<Ctrl+Space>. Я буду сильно удивлён, если это сработает (и ещё больше, если при этом init'а не будет).

Livaanderiamarum 29.12.2011 00:38

Цитата:

Сообщение от B@rmaley.e><e (Сообщение 146910)
Этот подход тем более плох. Не надо решать за пользователя, куда записывать объект.Да. Возьмите свой исходный код, добавьте его в проект, а в соседнем файле наберите myToolbox.<Ctrl+Space>. Я буду сильно удивлён, если это сработает (и ещё больше, если при этом init'а не будет).

вижуал студио справился) нетбенс 701 справился

B@rmaley.e><e 29.12.2011 01:30

Цитата:

Сообщение от Livaanderiamarum
нетбенс 701 справился

И как он справился? Вывел свойства прототипа Object? Успех, да.


Печально, но ни Eclipse JSDT, ни Netbeans не распознали ни одну из конструкций
var a = (function () {return obj})()
var a = ({ get : function () { return this } }).get()


UPD: Впрочем, в Эклипсе это исправимо.

Livaanderiamarum 29.12.2011 02:15

Цитата:

Сообщение от B@rmaley.e><e (Сообщение 146953)
UPD: Впрочем, в Эклипсе это исправимо.

А эклипс можно русифицировать? А то я его настроить не могу, потому что английский плохо знаю.

trikadin 29.12.2011 02:18

Цитата:

Сообщение от Livaanderiamarum
А эклипс можно русифицировать?

Лучше себя "англофицировать", полезнее будет ;)

Livaanderiamarum 29.12.2011 02:29

Цитата:

Сообщение от trikadin (Сообщение 146962)
Лучше себя "англофицировать", полезнее будет ;)

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

trikadin 29.12.2011 02:57

Цитата:

Сообщение от Livaanderiamarum
Как ты сделал в свое время?

Сидел и переводил. У меня, кстати, до сих пор IDE на английском, и я даже не задумываюсь о русификации...

Постепенно запомнишь главное, ну а если уж понадобится что-то тонкое - словарь к твоим услугам)

melky 29.12.2011 08:46

Цитата:

Сообщение от B@rmaley.e><e (Сообщение 146910)
Этот подход тем более плох. Не надо решать за пользователя, куда записывать объект.

опять не понял. т.е. вы за то, чтобы при запуске jquery возникал prompt, куда вводилось имя переменной ($,jQuery -> prompt("введите имя переменной") )?
чем это плохо ?

PS комод не справился.

B@rmaley.e><e 29.12.2011 12:31

Цитата:

Сообщение от melky
опять не понял. т.е. вы за то, чтобы при запуске jquery возникал prompt, куда вводилось имя переменной ($,jQuery -> prompt("введите имя переменной") )?

В данном случае пользователь — пользователь библиотеки / модуля, а не человек, открывший страницу в браузере.
Цитата:

Сообщение от melky
чем это плохо ?

Тем, что теряется гибкость. Может быть, я хочу, чтобы jQuery жил в каком-нибудь window.utils.jQuery?

Livaanderiamarum 29.12.2011 12:34

Цитата:

Сообщение от B@rmaley.e><e (Сообщение 147039)
В данном случае пользователь — пользователь библиотеки / модуля, а не человек, открывший страницу в браузере.Тем, что теряется гибкость. Может быть, я хочу, чтобы jQuery жил в каком-нибудь window.utils.jQuery?

тут все вопросы к jQuery он специально так сделан чтобы был доступен в GO? а соответственно везде в коде.
если хочешь чтобы он был доступен в window.utils.jQuery, ты не поверишь, но делай так:
window.utils.jQuery = $

melky 29.12.2011 18:16

B@rmaley.e><e. иногда пишут в аргументах самоисполняющейся функции объект экспорта (т.е. куда будет экспортирована переменная)

но в случае jQuery переменная экспортируется в шорткат window. сделано, видать, чтобы два раза window в аргументах не писать.

(function(window, varName, exportObj){
      window.getComputedStyle...
      exportObj[varName] = jquery.
})(window/*shortcut*/, "jQuery"/*var-e name*/, window /*export obj*/);


Цитата:

Сообщение от Livaanderiamarum (Сообщение 147041)
тут все вопросы к jQuery он специально так сделан чтобы был доступен в GO? а соответственно везде в коде.
если хочешь чтобы он был доступен в window.utils.jQuery, ты не поверишь, но делай так:
window.utils.jQuery = $

мы не об этом

B@rmaley.e><e 29.12.2011 19:10

Цитата:

Сообщение от melky
иногда пишут в аргументах самоисполняющейся функции объект экспорта (т.е. куда будет экспортирована переменная)

И смысл так писать, если можно просто объект вернуть? А если нужна локальная переменная? Объявлять объект и записывать ему свойство — какой-то костыль.

Livaanderiamarum 29.12.2011 23:26

Цитата:

Сообщение от B@rmaley.e><e (Сообщение 147109)
И смысл так писать, если можно просто объект вернуть? А если нужна локальная переменная? Объявлять объект и записывать ему свойство — какой-то костыль.

да( в целую строчку кода и в террагерцы вычислений(

_____________
и запомните люди, костыль, это когда пациент хромает.

melky 29.12.2011 23:40

Цитата:

B@rmaley.e><e прав, но истина дороже.
лучше использовать средний вариант, нежели объект с камикадзе-методом.


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