Как стать автором
Обновить

Комментарии 68

Есть вариант использовать геттеры и сеттеры в Жаваскрипте в ИЕ5+
habrahabr.ru/blogs/javascript/75158/
Одна проблема — только в глобальном namespace:( потому этот грязный хак практически неприменим в реальном проекте.
НЛО прилетело и опубликовало эту надпись здесь
плюсик в конце заметили?:)
НЛО прилетело и опубликовало эту надпись здесь
дополнил
Лучше проверять равенство через ===, а не через ==
Был дан "+", потом кто-то поставил "-" комменту.
Мне на рейтинг плевать, а вот почему я не прав, хотелось бы услышать :)
Это был не я. Но если вы имели в виду кусок с

typeof {}.__lookupGetter__ == 'function'

То там вполне хватило бы "==", потому что typeof в любом случае вернет String (либо undefined) и дополнительная проверка не нужна
function count(f, q){
	console.profile()
	while(q--){
		f();
	}
	console.profileEnd()
}
function f1( x ){
	return typeof x == 'undefined';
}
function f2( x ){
	return typeof x === 'undefined';
}

count(f1, 1000);
count(f2, 1000);


Рез-ты:
имя/всего/один вызов
f1/1.012ms/0.108ms
f2/0.811ms/0.001ms

Это крохи, но таких сравнений в коде огромное кол-во + легче отловить ошибки несоответствия типов.

function count(f, q){
console.profile()
while(q--){
f(String.ololo);
}
console.profileEnd()
}
function f1( x ){
return typeof x == 'function';
}
function f2( x ){
return typeof x === 'function';
}

count(f1, 1000);
count(f2, 1000);


Профилирование (2.264ms, 1000 вызовов)
Профилирование (2.311ms, 1000 вызовов)

В любом случае в данном конкретном случае нечего отлавливать, причину я уже писал выше, избыточный код.
во-первых как у вас получилась, что 1.012ms — это 0.108ms за один вызов, а 0.811ms — это 0.001ms
такая ситуация действительно есть когда мы проверяем (typeof undefined). потому что происходит сравнение (undefined == 'undefined') и потому оба значения приводится к булевому виду (Boolean (undefined) == Boolean ('undefined')). Именно приведение и занимает это время.

И действительно в IE оно будет проверять работать так

Но, эта проверка вызывается один раз при инициализации — так какая разница?
Это крохи, но таких сравнений в коде огромное кол-во + легче отловить ошибки несоответствия типов.

Кстати, спустя годы можно дополнительно понять, почему спичечные оптимизации не имеют смысла. Последний Хром:
function count(f, q){
    console.time(1)
    while(q--){
        f();
    }
    console.timeEnd(1)
}
function f1( x ){
    return typeof x == 'undefined';
}
function f2( x ){
    return typeof x === 'undefined';
}

count(f1, 100000000); //  181.000ms
count(f2, 100000000); // 1034.000ms
видимо, за отсутствие аргументов.
for (var i in topics.comments);
// vs
for (var i in topics.loadComments());

Может конечно первая запись более изящна, но вторая намного лучше подходит для продуктивной разработки ибо явно демонстрирует, что произойдет доступ к БД (или какой нибудь другой тяжелый запрос).

ЗЫ. Вообще не понимаю этого маниакального стремления прятать в геттерах тяжелые запросы. Эти грабли были уже посещены как минимум в EJB1...2, где из-за таких вот приемчиков генерировался нереальный сетевой трафик и огромное количество запросов к БД на каждый чих.
+1… Скрывать в геттере реализацию получения каких-то данных от БД не есть хорошо… Либо это уже будет не стандартный геттер/сеттер…
Для меня сомнительны преимущества этих геттеров/сеттеров. Оно вроде как короче и иногда меньше скобок требует, но надо помнить кто из них метод, а кто проперти…

Есть такой вариант что когда-то в коде обращались напрямую к некому филду у объекта, а тут мы раз! сделаем её пропертёй и при неизменном клиентском коде легко так подпилим серверный функционал в нужном направлении. Но это тоже сомнительное достоинство.
Может конечно первая запись более изящна, но вторая намного лучше подходит для продуктивной разработки ибо явно демонстрирует, что произойдет доступ к БД (или какой нибудь другой тяжелый запрос).


вот представим такую ситуацию с ORM.

var category = Orm.factory('category', id);
for (var i in category.topics) {
  var topic = category.topics[i];
  for (var k in topic.comments) {
    var comment = topic.comments[k];
    comment.author;
  }
}


Отлично, работает. Но при нагрузках начинает глючить. Лезем разбиратся и офигеваем от количества запросов. Меняем кусок:

var category = Orm.factory('category', id)
  .includes('topics', 'topics.comments', 'topics.comments.author');
for (var i in category.topics) {
  var topic = category.topics[i];
  for (var k in topic.comments) {
    var comment = topic.comments[k];
    comment.author;
  }
}


Орм делает один запрос с джоинами, или 4 запроса без джоинов и мы получаем отлично работающее приложение с тем же айпи, вместо:

var category = Orm.factory('category', id)
  .includes('topics', 'topics.comments', 'topics.comments.author');
for (var i in category.loadTopics()) {

А ведь топики уже загружённые уже, а судя по коду можно подумать, что они опять грузятся)

Но вообще — это инструмент, я никого не заставляю им пользоватся, если кто-то не согласен с таким подходом
А ведь топики уже загружённые уже, а судя по коду можно подумать, что они опять грузятся)

Ну так надо назвать метод по другому :-))
Что-то не приходит сходу название, подскажете?
getTopics()
а чем это отличается от .topics? все равно по названию нельзя понять, что там происходит тяжёлое обращение к базе.
Ничем, и не должно если УЖЕ загружено и это следует из предыдущего кода.
На самом деле точно такое же двусмысленное имя. Из имени совершенно не следует, что топики уже загружены с сервера в объект и метод их только копирует из внутреннего представления. Ну разве что при использовании в браузере это чуть привычно, что get — быстро получить, а load — загрузить сервера. А если Node.js/Rhino/Jaxer? Реализовать lazy loading такое название тоже не мешает.
так название и, возможно, документация должны говорить, что делает этот метод.
А от неправильного использования можно защититься с помощью разных проверок. Например, я бы сделал, чтобы get кидал исключение, если данные не были ранее загружены.
более того, реализация может менятся. сначала мы в этом методе грузим из базы. а потом — переписываем и грузим из кеша. потом переписываем и грузим в конструкторе. пользователю должно бытьт абсолютно всё равно. потому не вижу разницы между object.prop и object.getProp()
браузеры без поддержки свойств упадут при парсинге, а не исполнении.
Сдаётся мне, «изящный вариант» неоптимален — зачем всю работу проделывать при конструировании каждого объекта если можно сделать это один раз? Вобщем, с технической стороны это не вариант, да и изящества я не обнаружил.
я вас не понял, какую работу проделывать при конструировании каждого объекта?
А мне лично ближе аксессоры а-ля jQuery:

var Foo = new Class({
	test: function ( value ) {
		if( value === undefined ) {
			console.log('test getted');
			return 'test';
		}
		console.log('test setted');
		return this;
	}
});


Это удобнее тем, что сеттер может ещё вернуть какое-то значение: контекст для цепочек или удачность операции.
Так, правда есть немного надуманные или религиозные проблемы.
согласен, тоже люблю, когда сеттер возвращает значение.
Лично мне не хватает геттера и сеттера, которые будут вызываться при обращении к несуществующему свойству или методу.

Чтобы вместо

function Foo(bar) {
	this._bar = bar;
};
Foo.prototype = {
	set bar (bar) {
		this._bar = bar;
	},
	get bar () {
		return this._bar;
	}
};


можно было так

function Foo(bar) {
	this._bar = bar;
};
Foo.prototype = {
	__set (name, arg) {
		this[name] = arg;
	},
	__get(name) {
		return this[name];
	}
};

Хотел поддержать, но потом подумал ещё раз и понял что так можно запутать код и при корявом использовании отлов ошибок станет адом.
Ну собственно сами по себе геттеры/сеттеры вводят в заблуждение скрывая вызов метода при обращении к свойству, так что запутаться можно в любом случае.
А вот выше приведенная конструкция бывает очень полезна, хоть и редко, но как говориться — метко.
Решается аналогом в апи: Foo.set( 'name', argument );
А отловить ошибки становится проще.
https://developer.mozilla.org/en/Javascript/Reference/Global_Objects/Object/noSuchMethod
про noSuchMethod я знаю, но к сожалению это не кроссбраузерно
ну геттеры и сеттеры — тоже. для сервера подходит отлично
Геттеры и сеттеры это то, чего ещё пока полноценно не хватает в JS, да. Ещё бы возможность следить за состоянием поля. Как здесь: https://developer.mozilla.org/en/Javascript/Reference/Global_Objects/Object/watch
посмотрите в сторону YUI3 — там есть атрибуты и события изменения значения аттрибутов
Да, я в курсе. Но предпочитаю нативную поддержку. Буду ждать.
Я думаю ваш патч не будет принят из-за несовместимости с некоторыми браузерами.
этот патч совместим со всеми браузерами. точнее не так.
те, кто не использует геттеры и сеттеры — ничего не узнают про этот патч, он на них не повлияет никак. а вот те, кто использует — сможет использовать их и в Мутулз.
этот патч совместим со всеми браузерами. точнее не так.
те, кто не использует геттеры и сеттеры — ничего не узнают про этот патч, он на них не повлияет никак. а вот те, кто использует — сможет использовать их и в Мутулз.

Если я начну использовать геттеры/сеттеры в своем скрипте, а он попадет в неподдерживаемый браузер, то что тогда?
Мой код
for(i in obj.property) { /* ... */ }

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

Лучше испозовать мутаторы, и оформить это как плагин, тогда: хочу — подключил, не хочу — и не надо.

Код который не работает во всех браузерах указаных на оффициальном сайте MooTools (а там пишет IE6+) не пройдет модерацию.
Там уже так и предположили. Если вы будете использовать геттеры/сеттеры, и они попадут в неподдерживаемый браузер — то он отвалится на этапе компиляции с синтаксической ошибкой в вашем коде, будет этот патч в мутулз или нет.

С Мутаторами решение там предложили и оно хуже, потому что:
1. Не такое удобное (надо заносить все такие свойства в Мутатор Properties)
2. Что самое главное — не наследуется через Implements, потому примешать код с геттерами и сеттерами не получит.
Гетеры и сеттеры IRL:
Тонкий намек на опечатку в статье: «Все, теперь сеттеры и гетеры реализуются и мы с лёгкостью можем их наследовать и использовать. Наслаждайтесь)».
getted? setted? английская языка оченно сложное.
минус за то, что подъебнули. исправил.
простите, не вижу, где
не видите что?
не вижу, где что исправлено.
Я тоже не вижу, что и где исправлено.

Smth is set; smth is got. Ибо глаголы эти — неправильные: get/got/got, set/set/set.
вместо того, чтобы подъебывать и разводить оффтоп, можно в личку написать, что не так.
исправил я опечатку в этом месте, а про irregular — забыл. у нас на экономике английский не преподают, а за 5 лет без практики много чего может вылететь.
Тебе помогают по существу сделать топик лучше, а ты ещё и не доволен?

P. S.: Интересно, откуда вообще берется желание использовать по факту незнакомый язык. Пиши на том, что знаешь.
а ты мне на хами.
по существу топик лучше не стал. исправилась грамматическая ошибка, которая не влияла на понимаемость топика.
более того, ошибка указана в недопустимом тоне. если хочешь помочь человеку сделать топик лучше — можно написать в личку, где и что исправить. что, обычно, нормальные люди и делают, вместо того, чтобы разводить в топике про Javascript обсуждение моего знания английского языка
И не указывай мне, что делать. На чём хочу — на том пишу. И судя по рейтингу топика, большинству понравилось, как я пишу.
Уверен, если ты напишешь пару текстов на английском, то лингвисты тебе тоже тыкнут носом в несколько ошибок, умник.
1. Конкретные цитаты хамства с моей стороны последуют?

2. Налицо взаимоисключающие параграфы: рекомендации, что делать другим, раздаём, от аналогичных рекомендаций в свой адрес боли пониже спины испытываем. Забавно.

3. Гипотетические лингвисты не услышат от меня ничего, кроме «спасибо». Но это ж я, а не.
я бы посмотрел на вас после подъёбок и рекомендаций перестать пользоваться английским языком от гипотетических лингвистов.
По секрету сообщу, что скиллы «моральная устойчивость» и «чувство собственного достоинства» неплохо прокачиваются.

Кстати, где ж примеры моего хамства?
а ты ещё и не доволен?

Живо представил муки души поэта от настолько прямо поставленного вопроса :)
у меня больше нету желания разводить флейм и кормить тролля
Однако ж, всем известно, кто первый кричит, «держи вора» :)

Топик ты поправил, молодец. Надеюсь, «спасибо» говорить когда-нибудь научишься.
Только мне кажется, что этот синтаксис геттеров и сеттеров выбивается из общей красивости js? Начиная с именования в стиле __xxx__, которое явно из питона притянуто (и вроде бы ранее в js не встречается), и заканчивая имхо неприлично большим количеством методов в object для поддержки геттеров и сеттеров.

Такое ощущение, что это расширение стандарта делал какой-то другой человек, отличный от изначальных идеологов js.
Так и есть: в стандарте не слова о __xxx__ методах. Getters и setters это часть стандарта ES5. Автор либо поленился изучить вопрос, либо поленился об этом написать. Вместо того чтобы рассказать о стандарте и его поддержке, он рассказывал о proprietary свойствах.

Вот почитайте лучше это: dmitrysoshnikov.com/ecmascript/es5-chapter-1-properties-and-property-descriptors/
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории