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

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

Жаль, что много неверных и спорных сниппетов. Pull'ить и pull'ить :)
НЛО прилетело и опубликовало эту надпись здесь
некоторые так вообще запредельный ****ец
НЛО прилетело и опубликовало эту надпись здесь
Начало положено? Да там надо 80 удалить и написать иначе.
НЛО прилетело и опубликовало эту надпись здесь
Главная проблема, что, при желании изменить, под каждым из пунктов затянется холивар на 200 комментов да ещё и на английском языке. У меня нет сил на такое.
НЛО прилетело и опубликовало эту надпись здесь
Для ряда «оптимизационных» косяков можно на jsperf'e налабать примеров.
Ну а так да, это едва 20-30% спорных пунктов, которые нужно выпилить или хотя бы подкорректировать.
Да, собеседование не прошел бы…
jQuery сам по себе один большой антипаттерн.
НЛО прилетело и опубликовало эту надпись здесь
Интерпретатор попытается привести document.attachEvent к типу Boolean. Так можно, но это не нужно, лишняя операция.
(Получить тип + сравнение) vs (Привести к булевому + сравнение). И там и там две операции.
Я чуть ниже привел код. === и !== не делает приведение.
if(document.attachEvent !== undefined) ...
Все заблуждаются. Есть огромное количество «правильных» способов. Например:
if ('attachEvent' in document) // это явно лучше, чем глупая проверка на undefined
if (document.attachEvent == null) // или вот так можно
if (typeof document.attachEvent == 'function') // нам ведь нужна именно функция, да?
Крокфорд рекомендует глупую проверку на undefined или hasOwnProperty() вместо 'in'
И что? У Крокфорда, при всём моём уважении к нему, куча заблуждений и «пунктиков».
Хотя бы один аргумент, почему document.attachEvent надо проверять на undefined, а не на function? Чем проверка на undefined лучше, чем сравнение с null? И так далее.
тем, что паттерны и стандарты хороши не тем, что они чем-то лучше других, а тем, что они стандарты :)
Чем проверка на typeof == undefined стандартнее проверки на равенство null? В том же jQuery чаще проверяется именно на равенство с null
Мы проверяем существует ли свойство или нет (то есть undefined). Мне кажется куда логичнее проверять на undefined путём сравнения с undefined, хотя сравнение с приведением типов с null тоже в данном случае сработает.
Нет, вы проверяете свойство на неопределённость и только то, что при обращении к несуществующим свойствам вы получаете undefined, а не exception даёт вам инструмент. Сам факт наличия свойства можно проверить одним из методов — через hasOwnProperty для собственных свойств и in для всего прототипа.
(function (undefined) {
  var object = { foo: undefined };
  console.log( typeof object.foo != 'undefined' ); // false - свойства нету? О.о
  console.log( 'foo' in object );                   // true - есть
  console.log( {}.hasOwnProperty.call( object, 'foo' ) ); // true
})();
хотя сравнение с приведением типов с null тоже в данном случае сработает.

Это не «сравнение с приведением типов», это «нестрогое сравнение». Вполне возможно, что именно этот случай оптимизирован и очень быстр:
м
operator equals (left, right) {
  if ( (isNull(left ) || isUndefined(left )) &&
       (isNull(right) || isUndefined(right))) {
    return true;
  }
  // тут проверяем типы и так далее
}

Так что аргумент «мне кажется, что такой способ быстрее» — это вилами по воде.
я не приводил этот аргумент, более того в соседней ветке заявил, что в данном контексте, он по моему мнению абсолютно бессмысленен
Ну там снизу стараются меня убедить в этом =)
НЛО прилетело и опубликовало эту надпись здесь
Я об этом и говорю — опиратся на оптимизацию в этм месте это просто заблуждение
Если заранее известен конкретный тип (function), то, конечно, лучше проверять сразу на него.
ну и чёткое сравнение с undefined на 0,0001% теоретически лучше чем сравнение с приведением типа с null, 0 или пустой строкой (непомню уже, пустая строка false?)
0, false и '' не равны null.

А чем теоретически лучше даже на 0,0001%, чем сравнение на null?
0, false и '' не равны null.

Да, вы правы.

Про null выше ответил
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Рекомендуется он в соответствии с теорией, что сравнение без приведения типов (== vs ===) чуть быстрее по скорости.

Теория ошибочна. Приведение типов не происходит, если обе стороны выражения — одного типа. Так что сравнивать string со string можно одинаково что двойным, что тройным равно.
Лишняя операция в document.attachEvent == null, это полностью аналогично такому коду
if(!!null === !!document.attachEvent) ... // !! - самый короткий путь приведения к boolean


Лишний вызов typeof и создание лишней строки
if (typeof document.attachEvent == 'function')


А такой вариант интересный, никогда не использовал.
if ('attachEvent' in document)
Вряд ли на каждый вызов typeof создается новая строка, скорее всего там используются константы.
Лишняя операция в document.attachEvent == null, это полностью аналогично такому коду
if(!!null === !!document.attachEvent)

Заблуждение на заблуждении) Вот пруф, что это не так:
(function () {
  var document = { attachEvent: false };
  console.log(   document.attachEvent ==   null ); // false
  console.log( !!document.attachEvent == !!null ); // true
})();
Ну… мой вариант полностью рабочий.
console.log( !!document.attachEvent === !!null ); 


А этот код ваш, я его не проверял.
if (document.attachEvent == null) // или вот так можно


Т.е. вы написали неверный код, который я попытался привести к верному аналогу, но он не заработал, т.к. изначально были неверные данные.
Мой код вполне рабочий. Вы ошиблись в том месте, где сказали, что эти варианты «полностью аналогичны». Нет, вы заблуждаетесь, они совершенно не аналогичны, хотя в большинстве случаев и будет одинаковый результат.
Смотрите ниже, у меня в консоле хрома ваш код не работает.
Не знаю почему true всегда, я null почти никогда не использовал.
  var document = { attachEvent: false };
  console.log(   document.attachEvent ==   null ); // true
  console.log(   document.attachEvent1 ==   null ); // true
Все, я запутался… %) Выхожу из боя…
document = { attachEvent: false };
  console.log(   !!document.attachEvent ===   !!null ); // true
  console.log(   !!document.attachEvent1 ===   !!null ); // true
Не вижу отличий по работе, вообще никаких.
Зачем вы меня дурите?
Извиняюсь, обрезать нечем.
xmages.net/storage/10/1/0/e/6/upload/83278187.png

P.S. Оффтоп. Есть сервис для заливки, без регистрации и сразу сделать crop?
Тут кажется оберка сыграла роль, с ней у меня также… document кажется нельзя переопределить, не знал об этом.
Глобальный document не переопределяется. Если сделаете console.log( document ), то поймёте в чём ваша ошибка. Я не зря оборачиваю код в анонимную функцию
Мне казалось в JS переопределяется все и везде. Это скорей всего ограничение браузера, в спецификациях нет глобальных переменных window и document.
Это API. Вполне возможно, что согласно API document определяется как-то так:
Object.defineProperty( window, 'document', {
  configurable: false,
  value: new Document()
});

Тогда переопределить его будет нельзя:

(function () {
 var obj = {};
 Object.defineProperty( obj, 'test', { configurable: false, value: 1 });
 obj.test = 2;
 console.log( obj.test ); // 1
}());


(function () {
 'use strict';
 var obj = {};
 Object.defineProperty( obj, 'test', { configurable: false, value: 1 });
 obj.test = 2;
 console.log( obj.test );
 // Cannot assign to read only property 'test' of #<Object>
}());


Моё предположение подтверждается этим:
(function () {
 'use strict';
 window.document = 1;
 // Cannot assign to read only property 'document' of [object DOMWindow]
}());
Можно было и не гадать :)
Object.getOwnPropertyDescriptor(window, 'document');
// {"configurable":true,"enumerable":true,"writable":false}
Действительно, что эт я? =)
w3c: www.w3.org/TR/Window/#dfn-window-interface
ну и в html5-главах тоже расписана структура объекта window, причём куда более подробно и конкретно.
Логично предположить, что каст стоит дороже, чем получение типа.
А оператор in не обходит ли все свойства объекта, чтобы понять есть ли в нем указанное свойство?
Второе опять же каст. Третье согласен можно и так.
Ну вот все эти размышления что тут стоит дороже и есть основной антипаттерн )
Ну я лишь пытаюсь обосновать выбор именно того средства. А когда делаешь паттерн, то вполне логично использовать максимально быстрые методы, ибо лишняя миллисекунда порой превращается в лишнюю секунду.
В случае с JS лучше выбрать способ покороче, т.к. неизвестно, какой из способов является на самом деле быстрее, а в клиентском коде важен размер (чем меньше — тем лучше)
Это если ты не пишешь рендер, или какие-то другие могучие алгоритмы для обработки огромного кол-ва данных. Для простых приложений проблема преждевременной оптимизации не так критична.
Плюс там так и написали, что хорошо использовать так, но, а если будете вот так, то вообще крутые ребята.
Я говорю о том, что ваша «оптимизация» на практике может быть даже «антиоптимизацией». И в чём крутые ребята, если оно работает медленнее, записывается длиннее, а действует ничем не лучше?
Сейчас проверил в хроме, у меня typeof на 14% быстрее, чем in. При этом простое сравнение свойства с undefined работает почти на 40% медленнее чем in. Так что никаких заблуждений здесь нет, ребята показали максимально эффективный код.
(function (undefined) {
 var count = 10000000, i;

 console.time( 'typeof' );
 for (i = count; i--;) (typeof undefined == 'undefined');
 console.timeEnd( 'typeof' ); // 71

 console.time( 'null' );
 for (i = count; i--;) (undefined == null);
 console.timeEnd( 'null' ); // 54
})();


Так что заблуждение есть. Ребята показали максимально длинный и, при этом, неэфективный код.

Но заметьте, разница в 17 мс на 10 миллионах вызовов!
И стоит убрать объявление undefined из заголовка функции (чтобы получать глобальную, а не локальную переменную), как время вырастет в десятки раз:

(function () {
 var count = 10000000, i;

 console.time( 'typeof' );
 for (i = count; i--;) (typeof undefined == 'undefined');
 console.timeEnd( 'typeof' ); // 2334

 console.time( 'null' );
 for (i = count; i--;) (undefined == null);
 console.timeEnd( 'null' ); // 2307
})();


Так что просто получение значения глобальной переменной намного дольше, чем эти операции.

Потому ещё раз говорю — не занимайтесь глупостями.
Вот странно, мне кажется, что «even better» на главной — это не самое лучшее решение. Зачем узнавать тип, если undefined… всегда undefined…
if(document.attachEvent !== undefined)
  document.attachEvent('onclick', someFn)


Всегда писал так, уверен, что это 100% правильно. Может меня кто-то поправить?
Теоритически переменная undefined может существовать. Раз это возможно (пусть даже все понимают что строчку «var undefined = function(){}» мог написать только отъявленный психопат), то ваш подход не 100% правильный.
Мой модход 100% железный, всегда и всюду предохраняйся…
(function(undefined){
    console.log(windov === undefined); 
})();
Так антипаттерн как раз в том, что люди так не делают. Код приведенный вами в первом комменте без уточнения — антипаттерн.
Т.е. такой код… антипаттерн?
Application.closure.apply(function(a, u, j, undefined){
  //Эти сокращения хорошо задокументированны
  //a - application
  //u - underscore
  //j - jQuery
});


А вообще такой код используется в jQuery именно для того, чтобы нельзя было переопределить undefined и сломать код.
(function(undefined){
})();

+ такой код вообще не меняет стандартное поведение, это лишь страховка.
Первая строка кода… без комментариев и уточнения, это обычный хак JS.
code.jquery.com/jquery-1.7.2.js
Вы немного путаете (привожу код из jquery):
(function( window, undefined ) {   // смотрим описание функции, второй параметр называется undefined

})( window );  // смотрим вызов этой функции, передан только один аргумент, значит тип второго будет действительно undefined


В вашем же примере:
Application.closure.apply(function(a, u, j, undefined){  // здесь именно вызов функции, без контекста выглядит что undefined - это обычная переменная, и вы ее куда-то передаете. Выглядит как антипаттерн
  //Эти сокращения хорошо задокументированны
  //a - application
  //u - underscore
  //j - jQuery
});
Общая форма, её я привел самой первой.
(function(undefined){
    console.log(windov === undefined); 
})();


Пример с Application.closure.apply — это практическое применение, которое задокументированно в проекте.
JSLINT (http://jslint.com/) и многие IDE не любят такого, так как причесляют undefined к reserved words.
«причисляют», пардон
Раз мы ударяемся в дебри того, что кто-то мог переопределить undefined, то тут мы должны дойти до того, что этот же псих мог бы переопределить attachEvent. Что, кстати, мне кажется более имеющим смысл.
глобального «undefined» нет в старых IE
5.5 и меньше? Ну и что?
это переменная не освящена стандартом, в отличии от typeof. хотя может и ошибаюсь.
Открыл первый pdf из гугла «JavaScript Language Specification»…

The typeof operator returns a string indicating the type of its operand. The
string returned is one of
• “undefined”
• “object”
• “function”
• “number”
• “boolean”
• “string”


И целая глава из одного предложения.
The Undefined Type
Any variable that has not been assigned a value is automatically of type
undefined.
Ключевое слово: the string returned

то есть typeof a == 'undefined' — это согласно стандарту, а просто undefined — на совести разработчиков браузеров
Эм, я согласен, что мой англ не идеален. Но я кажется верно прочитал эти строки.
> string indicating the type
> The Undefined Type
> a value is automatically of type undefined.

А ваш пример только намекает, что в JS нет констант.
> the string returned
Не, есть в стандарте.
Конкретно раздел «15.1 The Global Object».
Там описаны еще NaN, Infinity, eval, к примеру.
Листаю паттерны JQuery — в целом всё понятно, многое очевидно, но тут внезапно:
в первоисточнике к одному паттерну (который, кстати, никак не прокомментирован) сказано:

// regular
$(elem).data(key, value);

// OMG like 10x faster
$.data(elem, key, value);


Объясните, в чем магия второго способа? Мне сложно представить, в чем кроется прирост производительности.
Походу это два совершенно разных метода, делающих разные вещи
Это 2 разных метода, точнее метод и функция. $.data() что называется «low level implementation», поэтому работает в разы быстрее.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории