Pull to refresh

Comments 185

Почему его? Почему не TypeScript? Последний ближе к нативному JS чем, CS от которого явно веет Ruby
От CoffeeScript явно не веет Ruby. Там больше от Yaml и Python.
Я пишу на Python последние 5 лет. Им там не пахнет :)
Я на Ruby второй год, им там тоже не пахнет :)
Из вики:
CoffeeScript is a programming language that transcompiles to JavaScript. The language adds syntactic sugar inspired by Ruby, Python and Haskell

Предлагаю тогда свалить все на хаскел, поскольку оба на нем не пишем :)
Вы что, прикалываетесь? Какой Haskell? Его в СS не больше, чем в JS!
Ниже я привел общие сходства для Python и Ruby.

Если говорить о Ruby, то это:
— именованные операторы (and, or, not, is (также общие и для Python, кроме оператора is)),
— операторы диапозона (.., ...),
— операторы определения (?),
— операторы экзистенциальности (?, ||=, ?=)
— оператор доступа (@),
— однострочные комментирии (#, также общие и для Python),
— инструкции (until, case/when, when, do, unless, super),
— expression substitution (#{}),
— диапазоны (ranges)
— значения по-умолчанию (есть и в Python)
— необязательный оператор вызова метода ()
— переменное чисо параметров (splats)
— возвраемое значение по-умолчанию (return statement)

и т.д.

И да, никто не утверждает что CoffeeScript это Ruby или Python.
>> операторы диапозона (.., ...),
а в пайтоне такого нет?

>> операторы определения (?),
это вообще бред полнейший, в руби такого «оператора» нет (если вы не о тернарном операторе конечно), просто в руби имя метода может содержать '?'.

>> — оператор доступа (@),
это тихий ужас в cs, в руби @ ссылается на переменную текущего объекта, а в cs оно может ссылаться и на метод, что очень не красиво выглядит.

>> необязательный оператор вызова метода ()
ну и что дальше-то? в cs «метод» без этого оператора все равно не вызовется, про убогий do знаю.

Уже 2 недели пишу на cs и пока так и не понял, мешает он мне или помогает.
>> операторы диапозона (.., ...),
а в пайтоне такого нет?

Не совсем, см. Ellipsis и NumPy

>> операторы определения (?),
это вообще бред полнейший, в руби такого «оператора» нет (если вы не о тернарном операторе конечно), просто в руби имя метода может содержать '?'.

1.
a = foo? bar


var a = typeof foo === "function" ? foo(bar) : void 0;


2.
a = foo ? bar


var a = typeof foo !== "undefined" && foo !== null ? foo : bar;


А теперь Ruby:

defined? foo
defined? foo(bar)


Не знаю как вам, но мне кажется что в CS это частично пришло из Ruby.

Тернарного оператора (:?) CS, нет также как и Python (

Уже 2 недели пишу на cs и пока так и не понял, мешает он мне или помогает.
Чем он конкретно он мешает?
По поводу '?' я до сих пор не понимаю, причем тут руби :))

Вот смотрите, пишем на cs:

x = 1
if x? then alert(1)

оно раскрывается в js:

if (x != null) {
alert(1);
}

Более того, '?' в кс что-то совсем уж «глупое», ибо я могу написать x?? и оно раскроется в:

if ((x != null) != null) {
alert(1);
}

В руби нет оператора '?', которое можно «впихнуть» в конец переменной :)
в руби можно определить метод с? в конце, так же как и с '!' в конце, но это ни на что не повлияет, это типа средство, позволяющее делать имена методов выразительнее. А в cs это реально функциональный юнит. Так что напрасно говорят, что это из мира руби, это из мира ленивых js разработчиков, которые вечно проверяют все и вся на != null и != undefined… :)
Ну многое смущает, правда, например эта же история с тем, что я могу написать «x = 1; x?; x????????» и последнее будет валидно и скомпилируется.

Они взяли @ из ruby, мол чтобы не писать this, но при этом в руби я всегда знал, что @ -> это объект, а не метод, потому никогда и не пробовал писать `@field()`, в cs'е же постоянно приходится писать `func()`, что выглядит не естественно и создает только путаницу для руби программистов вроде меня.

Мне не очень понятен синтаксис опредения функции, `(x) -> ()` — выглядит очень неряшливо и легко теряется в коде.

В том же руби: `lambda { |x| }`, или `->(x) {}`
или ерланге: fun(x) ->
или даже в plain-js: 'function() {}'

Короче говоря, cs вроде бы должен был стать удобным и читаемым, но получился перебор, много сахара, слишком много, там где сахар этот вообще не нужен, где-то стало не читаемее, а только хуже.

Но и плюсы конечно тоже есть, видимо :))
я могу написать «x = 1; x?; x????????» и последнее будет валидно и скомпилируется.

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

Мне не очень понятен синтаксис опредения функции, `(x) -> ()` — выглядит очень неряшливо и легко теряется в коде.
Мне наоборот нравится такая запись.

Однако ваша запись больше похожа на вызов функции с функциональным аргументом:

x -> (x)


А определение самовызывающихся лаямбда-функции выглядит так:
((x)->)(x)
do (x) -> x


И заметьте в отличии от Ruby, метод call опционален!
foo = -> 1
do foo


Такой синтаксис очень удобен для работы с функциональными аргументами:

fn -> x

Ведь даже такая запись:

-> 1


Вполне валидна (хотя и бессмыслена)

Коль вы упомянули JS, то этот синтаксис основан на будущем стандарте ES6.
wiki.ecmascript.org/doku.php?id=harmony:arrow_function_syntax
wiki.ecmascript.org/doku.php?id=strawman:block_lambda_revival

К сожалению не могу найти ссылку, когда в Python-сообществе обсуждали новый синтаксис для лямбда-выражений. Помню что большая часть предлагали именно подобный синтаксис!

но получился перебор, много сахара, слишком много, там где сахар этот вообще не нужен

Я бы тоже самое сказал про Ruby )
Спасибо за ответ.

Тут понимаете в чем дело, js это такой язык, где правят функции высшего порядка, и потому мы постоянно встречаем передачу функций в аргументах, причем определяются эти функции «на месте»:

_.select(collection, function(e) { return e > 1 })

и все это время что я пробую cs мне очень неудобно писать функции в стиле cs, вот пример:

_.select collection, (e) -> e > 1

потому как сигнатура определения функции очень слабая и еле заметная. Вот собственно и все мои притензии, то есть было бы как в ерланге:

_.select collection, fun(e) -> e > 1

Было бы как по мне гораздо проще :) Именно поэтому я в руби никогда не использую «короткий» синтаксис определения лямбды `->(e) {}`, а всегда использую классический вариант `lambda { |e| }`, потому что сигнатура заметнее :)

Это очень субъективно, но не заметить сигнатуру функции в CS очень просто и мне не нравится это, надеюсь я имею право на такие замечения к авторам языка :)

из опыта — просто сделайте перевод строки сразу после стрелки
_.select collection, (e) ->
    e > 1
Частичное сходство все-таки есть:
Идентация, лямбда-выражения, ленивые вычисления, списочные выражения (array comprehensions), destructuring assignment и пр.

Он решает треть проблем, описанных в статье.
Но синтаксис отличается очень сильно.
Я с этим не спорю. Мне проще за один день запомнить новый синтаксис, чем писать вары и точки с запятой.
на момент публикации (январь 2009)
CS у всех на слуху, следовательно вероятность найти ответ на SO гораздо выше.
Какая разница чем от него веет? Он решает кучу проблем JavaScript, это важно. Правда я мало знаю про TypeScript, может он и лучше. Но что за аргументы «похожее синтаксис», какая разница? Синтаксис изучается за один день.
Я за пирожком!
var result;
var container = document.getElementById('container');
var i = someArray.length;
  
while (i--) {
  result = 'my number: ' + i + result;  
  console.log(i);
}

забыл самое главное:

container.innerHtml  += result;
ИМХО, пока рановато за пирожком (подсказка). Кроме того, у вас будет вывод не в том порядке, что в оригинале (обратный счет)
Ет чо ето не в том? Обратите внимание на способ конкатенации.
Я имел в виду вывод в лог — console.log(i); В оригинале будет прямой счет, у вас — обратный. Конкатенация тут ни при чем.
А, вы за console.log()
Да кому он тут нужен? ))
Ваша «подсказка» увеличит расстояние до пирожка раз этак в 40 :)
Возможно. Но только тест меня ни в чем не убедил. Какой смысл гонять пустые циклы? Скорее всего, более-менее разумный JS движок их даже сможет оптимизировать и отбросить.
while (i--) намного медленнее, чем for (i = 0; i < someArray.length; ++i) из-за неявного приведения к boolean, проверял когда-то на JSPerf.
Опа, прикольно, будем знать.
И вообще, проверять на 0/не 0 нужно через ===0 и !==0 соответственно. Также и с boolean: ===true и !==true. Этим вы сможете избежать лишнего преобразования типов.
UFO just landed and posted this here
Если писать if (variable), то variable неявно приводится к булевому типу. Если тип переменной заранее неизвестен, то можно писать и так, тогда 0, null, undefined, '', false и некоторые другие вещи будут приводиться к false, съедая производительность. Если тип известен заранее, надо сверять с переменной/константой такого же типа для максимальной производительности.
UFO just landed and posted this here
Да, это исключение. Лично я всегда использую === и !== кроме проверки на null.
Не рановато ли за пирожком то?
Во-первых: не сильно то читаемый код
Во-вторых: 3 переменные в global scope
Я бы написал так
for(
    var i=0, 
        len=someArray.length, 
        container = document.getElementById('container');   
    i<len;

    container.innerHTML+='my number: '+i+'<br>', 
    i++
 );
Выглядит интересно, но у вас innerHTML в цикле модифицируется
Ну и читабельность тоже не на высоте
манипулирование innerHTML кусками или за один раз — практически никак (точнее совсем никак), после работы оптимизатора кода и обработчика структуры для корректной вставки в DOM — никак не влияет на скорость и производительность. Проверено на практике на огромных объемах. (И даже если это закешированный в переменную метод jquery, например) А вот лишних переменных во вне конкретного данного случая быть не должно совсем.

Опять же приведенный мной вариант отлично дружит в плане наглядности с jquery кодом.
Расшияемость — добавим обертку для .innerHTML как функцию (function(){ })() и вообще красота.
Отдайте пирожок!!! )
Мой пирожок, не отдам )

В вашем примере переменные все равно экспортируются в глобальную область видимости.
Мой код тоже можно завернуть в анонимную функцию; Так что тут 0 — 0
А касательно манипуляций с DOM, так не важно на сколько быстрей. Важно что быстрей; Вот тест например jsperf.com/accessing-modifying-innerhtml-in-a-loop
Ну ясен пень, что в javascript нет block scope. Имеется ввиду что их там семантически не должно бы быть)
А ваш тест запустил) Там вообще jquery победил.
Но вообще, в определенных случаях буфер конечно необходим, но, никак не тут.
Нету! let — это javascript а не ECMA.
а можна и без цикла)))
container.innerHTML = someArray.join('|').replace(/([^\|]+)\|?/g,function(){return 'my number: '+ (typeof p!='undefined' ? ++p:(p=0))+'<br>'});
но за скорость тут не ручаюсь. Не делайте так вообщем )
Не ну можно сделать хитрее:

'my number:' + join('my number: ') и т огда регулярка не нужна и ваще быстро
не не)) тут, как бы обрати внимание, не элементы массива выводятся, а их индекс ;)
А можно мне пирожок?
for (var i = 0, html = '', len = someArray.length; i < len; i++) {
   html += 'my number: ' + i;
}
document.getElementById('container').innerHTML = html;
да не нужен тут буфер!
синтетические тесты такие синтетические.
И куда он потом этот буфер html? delete? garbage collector'у? А вы в профилировщик заглядывали? delete или garbage collector жрут не мало.

Честно сказать, Ваш вариант намного труднее читается и выполняется. И если насчёт читаемости можно ещё поспорить, то насчёт производительности — нет. Попробуете сделать пару тестов, прежде чем напугать меня (и других) такими «непонятыми» словами.

Готовый тест: jsperf.com/my-js-patty
Мне это обсуждение очень напоминило обсуждения «оптимизаций» php-кода с заменой двойных кавычек на одинарные. :)

Да сто раз наплевать, пока профайлер не укажет, что это узкое место.
Я вроде про буфер уже говорил. Не надо в меня тестами кидаться. Вы суть то не уловили:
в данном примере, происходит инкремент html одного элемента, основанный всего лишь на индексе, не требующий дополнительных вычислений, требующих семантически выделить инкремент (конкатенацию) в блок действий for, а не в блок инициализации.

Смысл моего примера в том, что напрямую связанное с инкрементом единичное действие нефиг выделять в блок выполнения. Ему очень комфортно в итераторе. (проверьте тем же тестом)

Добавьте ваш семантически мусорный буфер в мой код и запустите тот же тест. Теперь мой код быстрее.

На реальной производительности (где на DOM куча вочеров, стилей, событий) наличие буфера никак не сказывается. А вот на «засорение» — да.

И вот пишут мне потом такие «спичечные» оптимизаторы: «посмотри ка мой код, что-то у меня не пойму все зависает после 15 минут работы, хотя везде все оптимизировано». Хотя не привыкать ловить минусы от непонимающих. Уже даже приятно как-то.
Я вроде про буфер уже говорил.

Да, говорили. Но в данный конкретный случай я с Вами не согласен.

Не надо в меня тестами кидаться.

А что нужно делать? Слепо следовать Вашему примеру и рассказать про сферических коней в вакууме? Нет уж, увольте — я буду использовать тесты чтобы доказать и понять что именно работает быстрее. Ведь именно программирование это то, что нужно всегда тестировать, дабы убедиться, что был выбран лучший вариант. Я вообще не могу представить себе программирование без тестов.

Вы суть то не уловили [...]

Не волнуйтесь, я заметил и понял Ваш пример, только автор статьи предлагал написать «как еще можно улучшить этот блок», а не «как втиснуть весь код в блоке for». Более того, я также заметил, что Вы не знаете, как работают переменные в JavaScript, плюс (по моему личную мнению) также не знаете как выглядит «читаемый код».

Смысл моего примера в том, что напрямую связанное с инкрементом единичное действие нефиг выделять в блок выполнения. Ему очень комфортно в итераторе. (проверьте тем же тестом)

Может ему и комфортнее там, но почему же не сделать код простым для понимания и в тоже время быстрым для выполнения? И да проверил, и ничуть не уступает, даже наоборот — он будет выполняться чуточку быстрее, если выделять его в блок выполнения (то есть, Ваш код уступает по всем параметрам). Тест jsperf.com/init-block-vs-for-block

Добавьте ваш семантически мусорный буфер в мой код и запустите тот же тест. Теперь мой код быстрее.

Стоп-стоп! Ведь Вы предлагали один вариант, а я совсем другой. В итоге, получилось что мой вариант оказался более чем в 600 раз быстрее Вашего именно из-за того, что я использую мусорный буфер. В то время как Вы, скорее всего из-за идеологических соображений, решили что для данного конкретного примера отдельная переменная зло. А теперь, когда Вы поняли свою ошибку, предлагаете мне использовать мой же метод? Нет уже, извините. То, что Вы не знаете как нужно работать с DOM используя JavaScript, это уже Ваша проблема.

На реальной производительности (где на DOM куча вочеров, стилей, событий) наличие буфера никак не сказывается. А вот на «засорение» — да.

Опять заблуждаетесь и рассказывайте другим сказки. На «реальной производительности» Ваш метод будет просто убить браузер пользователя и всё. Попробуйте тестировать Ваш пример, используя массив из тысячи элементов и пару десяток HTML элементов.

И вот пишут мне потом такие «спичечные» оптимизаторы: «посмотри ка мой код, что-то у меня не пойму все зависает после 15 минут работы, хотя везде все оптимизировано».

А как Вы вообще смеете написать мне такое? Вам совсем не стыдно? Если не заметили, в данный момент Вы являетесь спичечным оптимизаторов, который рассказывает сказки про какой-то там мусор, и бежит от него не понимая как можно оптимизировать простой JavaScript код. И если не заметили, именно Ваш пример зависает после 20 секунд работы (при реальных условия, где не будет использован только один HTML элемент и всего-лишь один массив из 100 компонентов).

Кстати насчет 15 я не согласен, при automerge могут вылезать конфликты. Лучше когда строчки можно добавлять/удалять независимо не затрагивая соседние. И где 16 пункт?
Только сейчас обратил внимание что 16 пункта нет в оригинале :(
Про автомерж — дельное замечание.
Значит и название статьи теперь не соответствует действительности. Обещали 24 совета, а в реале 23 :) Это как с пельменями, открываешь, а там полпачки — лёд :)
Не. Это больше похоже как сейчас любят делать производители молока — пишут 900 грамм и ставят рядом с литровыми пакетами по такой-же :)
Опаньки, я думал это у нас в Беларуси только.
Понимаю, что перевод, но…

17-й совет звучит неубедительно. Есть же ASI, являющейся частью спецификации ECMAScript. Слепо надеяться на точки с запятой тоже опасно.

Код ниже:
function sum (a, b) {
   return
     a + b;
}

Ничего не вернет, ибо вступает в дело ASI.

Вместо того что-бы давать необоснованные, а порой, и вредные советы, лучше бы разжевали как работает ASI.
Я считаю что наличие точек с запятой или их отсутствие должно относиться к coding style guidelines в рамках проекта или компании, но не более. Это не правило языка программирования.
Дока: www.ecma-international.org/ecma-262/5.1/#sec-7.9
Да, Вы правы. На ASI нужно сослаться. Не подумал. Сейчас добавлю.
Смысл этого ASI в том, что в середине 90-х решили: ой, если мы введём обязательные точки с запятыми, бедные веб-мастера удавятся от столь сложного синтаксиса.
Это не должно относиться к coding style, это должно быть обязательным.
Ваше «ой, если мы введём обязательные точки с запятыми, бедные веб-мастера удавятся от столь сложного синтаксиса», конечно же, убедительнее спецификации языка :)
Какая связь между убедительностью моих слов и убедительностью спецификации?
Основа современной спецификации писалась в тех же 90-х исходя из задач, которые тогда возлагались на язык.
Одна из задач — сделать язык как можно проще для простых смертных.
И эта часть спецификации является прямым следствием этого.
Я веду к тому, что в книгах и рекомендациях лучше объяснять, как работает на самом деле, а не как нравится лектору или писателю учебника. Ставить или не ставить точку с запятой это вопрос сугубо холиварный и не более. Правильно написанная программа работает и так и этак. Поэтому точкам с запятой место в coding style guidelines и я не согласен с вашей фразой:
Это не должно относиться к coding style, это должно быть обязательным.


Оно будет обязательным только тогда, когда будут (хотя маловероятно) внесены в спецификацию соответствующие изменения.
with, eval и неявное определение глобальных переменных тоже часть спецификации.
Можно обойтись без любого из представленных здесь пунктов и шансы написать работающую программу всё равно остаются.
Этоже статья не про то, что у вас без этого не будет запускаться скрипт. Это статья про то, как не быть маргиналом в мире js. Как писать более-менее сложные программы с тем, чтобы если кто-то читал ваш код, он не испытывал брезгливости.
Я понял вашу точку зрения. Но не могу согласиться с тем, что наличие или отсутствие точек с запятой (про with и eval я не говорю) является признаком говнокодерства. Есть прекрасные примеры из open source, с очень большим количеством коммиттеров, где в style guidelines точки с запятой убраны.
Соглашусь, что примеров таких репозиториев мало, но я знаю еще несколько. От достаточно авторитетного и не такого «ЧСВ-шного» как fat человека. Один из его нескольких: github.com/isaacs/npm. Причем в некоторых своих репах он использует точки с запятой. Ну и его мнение по этому вопросу: blog.izs.me/post/2353458699/an-open-letter-to-javascript-leaders-regarding
Я не понимаю, почему внизу той блогозаписи кенгуру.
Если вы имеете ввиду самый нижний элемент img, то он формируется из рандомного фото.
7. Нативное vs ненативное здесь не причём. Массив всё равно в цикле собирать придётся. Здесь просто нужно понимать, как строки внутри устроены.
UFO just landed and posted this here
Крокфорд ок. Меня очень раздражает node.js-like отступы в 2 пробела.

И как я уже писал IE7 не умеет JSON.Parse.
Если шестерку уже никто не поддерживает, то заказчики иногда требуют поддержки оного.
UFO just landed and posted this here
Использование везде JSON это сохранение единого coding-style. Проще для семерки подключить еще одну либу, чем писать обертки с евалом.
UFO just landed and posted this here
А обратно? В либе не только парсинг, но еще и сериализация есть.
UFO just landed and posted this here
Но там не говорится о том что используется только JSON.parse.
Использовать то о чем не говорилось в свою пользу — явная софистика.
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
17% чего?
На вопрос «кому нужен ие» — я ответил — заказчикам. Более того некоторые корпоративы еще и на ИЕ6 сидят.
UFO just landed and posted this here
Есть рынки, на которых доля покупок через ИЕ7 достигает 30%. JSON.Parse тут самое то
UFO just landed and posted this here
Ранее уже говорили, что иногда еще и stringify нужен.
Доля даже IE6 не смешна, к сожалению, а доверять нельзя даже данным, пришедшим со своего домена :)
Но я за jQuery.parseJSON, да, там как раз eval с предварительным тестированием, если JSON.parse нет в системе.
Читабельность хуже. 2 пробела придумали те кто любят писать лапшекод с кучей колбекэков.
Для вас хуже читаются два, для меня четыре. Кто прав?
В контексте дискуссии «Меня очень раздражает node.js-like отступы в 2 пробела» я, потому что речь шла обо мне.
Прав тот, кто пользуется табами и настраивает размер таба как ему нравится :-р
Мне двух пробелов мало, а четырёх много, так что мой код отличается употреблением трёхпробельного отступа.

(Правда, на Хабрахабре никто на эту особенность моего кода не обратил ни малейшего внимания за несколько лет — так что важность проблемы, вероятно, преувеличивается.)
UFO just landed and posted this here
UFO just landed and posted this here
а, теперь понял
но это вопрос к типографике )
надо будет у дизайнеров поспрашивать
UFO just landed and posted this here
… и с for с пробелом — внутри цикла ровный отступ
Но ведь всегда можно придумать симпатичную альтернативу
var foo = 1
  , bar = 2
  , baz = 3;
UFO just landed and posted this here
UFO just landed and posted this here
Спасибо, хорошая ссылка. Наглядно указали на некоторые плюсы и минусы такого стиля (comma-first и dot-first). В этой дискуссии обсуждают только JS, но мне довелось повстречаться в различных проектах с такой нотацией и в других языках. Иногда попадались интересные решения в стилях.

Я считаю, что очень важно что бы в проекте стиль был единым, а какой стиль выбран для проекта — не такой важный вопрос. IDE можно настраивать под стили и нотации каждого отдельного проекта, а глаз программиста достаточно легко перестраивается.
Не стал бы такое делать в JavaScript из-за автоматической вставки точки с запятой. Уже напоролся на
return
[], теперь стараюсь заранее указывать языку, что дальше не конец выражения.
Популряный совет «используйте jslint.com» весьма уныл с практической точки зрения. Вы правда думаете что кто-то ходит на регулярной основе на этот сайт и проверяет каждый свой коммит в JS там? Все такие вещи должны а) уметь быть запущенными локально б) прикручены к CI. Исключение может быть только если вы один в команде и делаете два коммита в год в js-файлы.

На самом деле из совета на эту тему — лучше сделайте npm install jshint Он как минимум «из коробки» куда более лояльный и практически применимый.
Разумеется это должно быть в CI и локально показываться в IDE. Смысл комментария показать инструмент. Кстати настройка и внедрение тянет на еще одну статью.
Кусок из настроек моего пичарма
image
в Notepad++ можно линт подключить.
в 18 пункте более «элегантная» форма записи выглядит довольно устрашающе. Тут наверное наоборот лучше полагаться на то что — не стоит писать длинных строк которые затрудняют восприятие кода.
И в примере выше (тот же 18 пункт) пропущена скобка: «if(object.hasOwnProperty(key)) {».
Ну это на любителя как говорится. У себя в питоне я привык использовать подобные конструкции
for x in (i in somelist if i > 3):
   ...

PS скобку добавил, спасибо.
И сам порой люблю пугать незнакомы с Питоном программистов конструкциями типа:
x = [(x) for x in (1,2,3) for y in (3,2,1) if x < y]


Но надо же быть демократичным.
ну это чересчур )
а вот внести один иф в цикл можно — читается просто и экономит 2 строки.
Давным-давно это не было редкой практикой использования аттрибута language у тега script.


Атрибут type=«text/javascript» тоже можно смело убирать.
У Ильи Кантора встречается более элегантная форма записи
for(prop in object) if (object.hasOwnProperty(prop)) {
    //...
}


но честно говоря я не уверен какие браузеры могут корректно обрабатывать ее.
Прим. пер.


Ведь все браузеры корректно могут, это ведь не специфическая конструкция, это просто

for (var prop in object)
    if (object.hasOwnProperty(prop)) {
        //...
    }


Object.hasOwnProperty есть во всех актуальных браузерах и даже в старых IE (начиная с 5.5).

На самом деле, казалось бы, всего лишь убран перенос строки, но код уже не кажется таким загроможденным. Вроде бы и просто догадаться, но как-то не думалось, что это на самом деле неплохое решение )
Круто! Спасибо, я думал это отдельная конструкция )
Тем не менее, это противоречит пункту 3
ого… вы не понимаете смысл этих элементарных строк кода?
После 5 лет питона это казалось вполне нормально лексеммой языка.
В названии забыли словосочетание «для начинающих» — в оригинале «24 JavaScript Best Practices for Beginners».

Статья действительно для начинающих разработчиков. Половина советов в стиле «Капитана Очевидность».

Но больше всего убил совет №2 «Eval = Bad». Это извращённое и неверное представление об eval.
Во-первых, eval всего лишь в 4 раза медленнее apply или call, но гораздо быстрее всех остальных методов. При этом замечание глупое, т.к. разности в скорости между методами для конечного пользователя не заметны.
Во-вторых, eval не угрожает безопасности приложения. Безопасности приложения угрожает отсутствие проверки данных на сервере.
Из-за этого тупого утверждения «Eval = Bad» большая часть приложений используют воистину извращённые способы выполнения кода на клиенте, но по сути те же eval.
Когда говорят что eval is evil, имеется в виду, что в большинстве случаев он не нужен и поэтому стоит подумать над альтернативными вариантами. Конечно, бывает, что он просто необходим.
Из-за этого тупого утверждения «Eval = Bad» большая часть приложений используют воистину извращённые способы выполнения кода на клиенте, но по сути те же eval.

Это лишь признак непонимания разработчиков сути утверждения eval is evil. Так как под eval имеются в виду исполнение стороннего кода вообще, любыми способами.
Eval плох, если в него вставлять пользовательские данные, а если собирать функцию «из кирпичиков» для оптимизации (JIT-компиляции в JS, например), то очень даже полезен. Но лучше не eval тогда, а new Function.
4. Используйте JS Lint

Перефразировал бы как «НЕ используйте JS Lint») долго сидел на нем и следовал фанатично всем мелочам. По факту — это того не стоит. Используйте JSHint.

Отдельно хочется заметить, что многие из приведенных примеров JS Lint бы не прошли)
Точно. Как написал автор этого форка — начиная с версии X js lint заставляет писать не как хорошо, а как автор js lint.
Запустил, получил кучу ошибок «используйте запись 24 == value» и ещё подобных, удалил, поставил jshint.
UFO just landed and posted this here
Один известный браузер с вами не согласен.
UFO just landed and posted this here
Насчет точек с запятой — регулярно встречаю этот совет от Кроуфорда и прочих, плюс его JSLint на это ругается.

Я встречал на практике только одну реальную проблему с этим делом — когда между return и значением ставится перенос строки. Обязательная точка с запятой проблему эту не решает. Эта проблема решается повсеместными египетскими скобками.

Я видел только один пример, где пропущенная точка с запятой может принести проблемы:
var x = 2
[1,2,3].map(function() { console.log(x); })

Может кто еще привести каких-нибудь, поближе к практике?

Вообще я считаю что тема слишком раздута — я писал и с точками с запятой, и без них, и ни разу не налетал ни на какие проблемы.
Читал, что если загнать код без точек с запятой в Google Closure Compiler например, то могут возникнуть проблемы. Т.е. при минификации/обфускации кода.
Если так — то это проблема оптимизатора, и нужно брать оптимизатор, который умеет работать по стандартам языка. Сильно сомневаюсь, кстати, что таким страдает гугловский оптимизатор.
Я встречал на практике только одну реальную проблему с этим делом — когда между return и значением ставится перенос строки. Обязательная точка с запятой проблему эту не решает. Эта проблема решается повсеместными египетскими скобками.

Как раз попросили обратить внимание на ASI ссылку на который я добавил.
===
6. Объявляйте переменные для вне циклов
===
Не сразу сообразил, к чему там «для» ))
и не «Объявляйте» а «инициализируйте», объявлять их можно где угодно (хоть после return), главное внутри функции.
для тех, кто часто работает с DOM'ом, добавляет что-то на страницу, в цикле например, то используйте

document.createDocumentFragment()

добавляйте в цикле в него то что необходимо, и потом уже делайте 1 раз append этого фрагмента куда надо на странице, сэкономите на перерисовке DOM'а
Мне много раз говорили о том что нужно объединять переменные под один var и разделять запятыми. Честно говоря мне кажется не очень наглядно тем неменее становится, экономии ни какой, крутые приложения на js счас принято минифицировать и как следствие все эти var'ы и так пропадут.
Довольно простые советы. Многие подходят и к другим языкам.

5. Переместите скрипты вниз страницы
Можно еще аттрибут async добавить.
Используйте комментарии

// Cycle through array and echo out each name.   
for(var i = 0, len = array.length; i < len; i++) {  
   console.log(array[i]);  
}  


Плохой совет. Надо писать код так, чтобы его не надо было комментировать. И уж представить себе совета по поводу комментирования хуже чем капитанить в комментариях к коду выше сложно себе представить
Надо писать код так, чтобы его не надо было комментировать.

Так обычно говорят после пары лет программирования. Пару серьезных проектов и это пройдет.

Капитан докладывает что капитанство по коду выше всего-лишь пример.
А можно пример? Лично я не вижу смысла комментировать код, если он качественно написан. Это все равно не даст новой информации. А вот всякие специфичные вещи из отрасли или сложные алгоритмы стоит комментировать, конечно.
font = ImageFont.truetype(self.FONT_FILENAME, int(self.lines_height[len(text)] * 2))
font_size = font.getsize(text)
font_img = Image.new('RGBA', font_size, 0)

mask = Image.new('L', font_size, color=255)
draw = ImageDraw.Draw(mask)
draw.rectangle((0, 0, font_size[0], font_size[1]), fill=0)
font_img.putalpha(mask)

draw = ImageDraw.Draw(font_img)
draw.text((0, 0), text, font=font, fill=self.COLOR) 
font_img = trim(font_img)

ratio = float(font_img.size[1]) / font_img.size[0]
height = int(ratio * self.line_width)
region = font_img.resize([self.line_width, height], Image.ANTIALIAS).crop([0, 0, self.line_width, height])
lines.append(region)


Убрал комментарии. Без них выглядит не очень читаемо.
Не лично вам, но все же
А когда код меняет свою суть, то комментарий не забываете обновлять?

Конкретно ваш пример прекрасно показывает то, что можно и без комментариев — достаточно лишь добавить немного функций
createFont() drawRectangle() drawText() extractRegion()

И все — теперь мы знаем, что делает код. Я скорее всего ошибся с названиями: их можно удлинить бОльшим количеством описания. В одном из проектов вполне можно было встретить что-то типа convertSingleSailInTwoSailsPerDayForMinskRoute()
Т.е. размазать логику по методам класса, при том что она используется только в одном методе? Ну уж увольте. Я лучше комментарии напишу.
Зачем размазывать? Давно придумали замыкания. И когда потом, через полгода, вам вдруг внутри функции, которую вы привели, надо будет изменить реализацию метода — вы сходу его найдете. Все потому, что 1. функции-замкания, которые вы сделали — маленькие, 2. они делают только одну вещь — создают шрифт, рисуют что-то, правят и т.п.

Я раньше тоже не мог без комментариев. Но попробовав без них в js теперь не могу себя заставить заставить сделать огромную функцию с кучей действий в других языках. Если функция делает две вещи — значит вам нужны две функции :)

Есть несколько вещей, для которых все еще допустим использовать комментарии с моей точки зрения:
1. описание зудобробильных регулярок
2. пометка регрессионных unit-test'ов номером задачи из баг-трекера
3. Странные действия. Например, в каком-то тесте, в отличии от десятка других, мы проверяем свойства расписания не понедельника, а вторника. Полезно написать, что это сделано потому, что во вторник поезда выбранного направления, например, на мойке :) Хотя, даже это можно инкапсулировать в getTestWeekdayForTrainById(trainId) и туда зашить логику… Хм… Пойду вкоммичу.
Что такое функции замыкания?
автор имел ввиду вложенные функции (которые, кстати, не всегда являются замыканиями)
я обычно оформляю подобные вещи таким образом:
function main(){
    //...
    doSomething();
    //...
    
    return;
    
        function doSomething(){
            //...    
        }
}

это облегчает чтение — когда видиш return, сразу становится ясно, что дальше никакого кода не выполнится.
почитайте про рефакторинг. один из основных запашков кода — это длинный метод.
Расскажите мне еще за фаулера, ага.
Вы считаете, что поменять название функции, если код в ней поменял свою суть никто не забывает и это проще, чем поменять комментарий?
// Create font
...
// Draw rectangle
...


А если подобный код, который продемонстрировал Azy, нужно выполнить в большом количестве итераций? Тут можно слегка сэкономить — не производя лишних вызовов функций (а иногда и в определении функций).
Как показывает практика — за названиями функций следят большем, чем за поясняющими его комментариями. Все-таки название функции — это часть кода, она «читается». А комментарии — это некий «шум»
поддерживаю. капитанские комментарии — зло. потому как часто случается, что код обновили — а комментарии нет.
Пишу сложный большой проект.
Комментарии в виде API документации (типа JSDoc) хорошая штука (да и решают все таки другую задачу)

Во всех остальных случаях: хочешь вставить комментарий, значит код написан криво и надо рефакторить.
7. Есть мнение, что + для строк работает сейчас быстрее, вот, например, пруфлинк: jsperf.com/string-concat-methods-test

А вообще, всем советую свежую книжку Effective JS Дэвида Хермана, очень неплохо объяснены прототипы, например (http://www.amazon.com/gp/product/B00AC1RP14/ref=oh_d__o00_details_o00__i00?ie=UTF8&psc=1)
UFO just landed and posted this here
Автор кода из пункта 7 не подозревает о существовании пустых массивов.
Вы так говорите, как будто с for в том же случае не надо проверять на непустоту. Не о том же речь.
Не надо. Зачем? Вариант с for'ом тем и хорош, что там всё естественным образом получается без дополнительных проверок, а вот вариант с join или будет производить неожидаемый результат, или будет нечитаемым (для инетерса попробуйте реализовать его таким образом, чтобы в случае нуля элементов возвращался пустой ul)

Не о том же речь.


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

Как по мне, так яблоки нужно сравнивать с яблоками.
А, вот вы о чем, понял. Все же чаще нужно, чтобы при пустом массиве не было ul вообще.
18. Оператор „for… in“
При проходе в цикле через свойстав обьекта вы также обнаружите что получаете в том числе и функции. Для избежания этого необходима проверка с if hasOwnProperty

Вы (автор или переводчик) о чем здесь вообще?
Я аж с перепугу перепроверил

var o = {a:1, f:function(){}}
for(var key in o) 
  if(o.hasOwnProperty(key)) console.log(key)
//a
//f
Автор вырезал текст из контекста, а переводчик наверное вчера только JavaScript начал изучать, толком не понимает еще о чем пишет )))
Но пост тем временем в плюсе. Эх… хабр уже не торт…
Переводчик написал свой комментарий, по поводу hasOwnProperty
Вообще Object.prototype.hasOwnProperty проверяет принадлежит ли свойство непосредственно обьекту а не его цепочке прототипов. Подробнее можно почитать в JavaScript Garden
У Ильи Кантора встречается более элегантная форма записи
это хорошо. но тем не менее ошибку автора вы скопировали и не исправили
И пишите свои посты, чтобы «был торт»
Имелись в в виду функции прототипов.
В любом случае „for… in“ перебирает не только функции методы прототипов, но все их свойства.
В любом случае я это знаю. Спасибо.
и вообще, если ваш объект приходится часто листать, то лучше установить его свойства с помощью defineProperty, чтоб ненужные свойства были not-enumerable
Можно кратко почитать статью, а можно просто почитать две полезные книги (вне зависимости от того, пишешь код на JavaScript, TypeScript или JavaScript) — Javascript: Good Parts и Javascript: Templates. (=
Воспользуйтесь прогрессивным улучшением (progressive enchantment)

Шутка, или опечатка по Фрейду? Мне понравилось ;)
Ещё по теме — Airbnb JavaScript Style Guide. Не думаю, что я полностью согласен со всеми пунктами, изложенными там, но в любом случае материал полезный и по текущей теме.
Sign up to leave a comment.

Articles