Pull to refresh

Comments 81

Жаль, что много неверных и спорных сниппетов. Pull'ить и pull'ить :)
UFO just landed and posted this here
некоторые так вообще запредельный ****ец
UFO just landed and posted this here
Начало положено? Да там надо 80 удалить и написать иначе.
UFO just landed and posted this here
Главная проблема, что, при желании изменить, под каждым из пунктов затянется холивар на 200 комментов да ещё и на английском языке. У меня нет сил на такое.
UFO just landed and posted this here
Для ряда «оптимизационных» косяков можно на jsperf'e налабать примеров.
Ну а так да, это едва 20-30% спорных пунктов, которые нужно выпилить или хотя бы подкорректировать.
Да, собеседование не прошел бы…
jQuery сам по себе один большой антипаттерн.
UFO just landed and posted this here
Интерпретатор попытается привести 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;
  }
  // тут проверяем типы и так далее
}

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

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

Да, вы правы.

Про null выше ответил
UFO just landed and posted this here
UFO just landed and posted this here
Рекомендуется он в соответствии с теорией, что сравнение без приведения типов (== 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
Не вижу отличий по работе, вообще никаких.
Тут кажется оберка сыграла роль, с ней у меня также… 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}
Действительно, что эт я? =)
Логично предположить, что каст стоит дороже, чем получение типа.
А оператор 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){
})();

+ такой код вообще не меняет стандартное поведение, это лишь страховка.
Вы немного путаете (привожу код из 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
это переменная не освящена стандартом, в отличии от 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», поэтому работает в разы быстрее.
Sign up to leave a comment.

Articles