Comments 185
25. Используейте CoffeeScript
Почему его? Почему не 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!
Тогда посмотрите LiveScript — форк CoffeeScript
Ниже я привел общие сходства для 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.
Если говорить о 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 и пока так и не понял, мешает он мне или помогает.
а в пайтоне такого нет?
>> операторы определения (?),
это вообще бред полнейший, в руби такого «оператора» нет (если вы не о тернарном операторе конечно), просто в руби имя метода может содержать '?'.
>> — оператор доступа (@),
это тихий ужас в 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… :)
Вот смотрите, пишем на 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 вроде бы должен был стать удобным и читаемым, но получился перебор, много сахара, слишком много, там где сахар этот вообще не нужен, где-то стало не читаемее, а только хуже.
Но и плюсы конечно тоже есть, видимо :))
Они взяли @ из 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 очень просто и мне не нравится это, надеюсь я имею право на такие замечения к авторам языка :)
Тут понимаете в чем дело, 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 очень просто и мне не нравится это, надеюсь я имею право на такие замечения к авторам языка :)
Частичное сходство все-таки есть:
Идентация, лямбда-выражения, ленивые вычисления, списочные выражения (array comprehensions), destructuring assignment и пр.
Идентация, лямбда-выражения, ленивые вычисления, списочные выражения (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()
Да кому он тут нужен? ))
Да кому он тут нужен? ))
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, съедая производительность. Если тип известен заранее, надо сверять с переменной/константой такого же типа для максимальной производительности.
А вариант while(i-- > 0)?
А если while(i-->0)?
Не рановато ли за пирожком то?
Во-первых: не сильно то читаемый код
Во-вторых: 3 переменные в global scope
Я бы написал так
Во-первых: не сильно то читаемый код
Во-вторых: 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(){ })() и вообще красота.
Отдайте пирожок!!! )
Опять же приведенный мной вариант отлично дружит в плане наглядности с jquery кодом.
Расшияемость — добавим обертку для .innerHTML как функцию (function(){ })() и вообще красота.
Отдайте пирожок!!! )
Мой пирожок, не отдам )
В вашем примере переменные все равно экспортируются в глобальную область видимости.
Мой код тоже можно завернуть в анонимную функцию; Так что тут 0 — 0
А касательно манипуляций с DOM, так не важно на сколько быстрей. Важно что быстрей; Вот тест например jsperf.com/accessing-modifying-innerhtml-in-a-loop
В вашем примере переменные все равно экспортируются в глобальную область видимости.
Мой код тоже можно завернуть в анонимную функцию; Так что тут 0 — 0
А касательно манипуляций с DOM, так не важно на сколько быстрей. Важно что быстрей; Вот тест например jsperf.com/accessing-modifying-innerhtml-in-a-loop
Ну ясен пень, что в javascript нет block scope. Имеется ввиду что их там семантически не должно бы быть)
А ваш тест запустил) Там вообще jquery победил.
Но вообще, в определенных случаях буфер конечно необходим, но, никак не тут.
А ваш тест запустил) Там вообще jquery победил.
Но вообще, в определенных случаях буфер конечно необходим, но, никак не тут.
Нету! let — это javascript а не ECMA.
А Вы что написали? Вы и написали: «…В javascript нет block scope».
Но есть. А в
Но есть. А в
ECMAScript
— есть в проекте 6-й редакции.а можна и без цикла)))
container.innerHTML = someArray.join('|').replace(/([^\|]+)\|?/g,function(){return 'my number: '+ (typeof p!='undefined' ? ++p:(p=0))+'<br>'});
А можно мне пирожок?
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 жрут не мало.
синтетические тесты такие синтетические.
И куда он потом этот буфер html? delete? garbage collector'у? А вы в профилировщик заглядывали? delete или garbage collector жрут не мало.
Честно сказать, Ваш вариант намного труднее читается и выполняется. И если насчёт читаемости можно ещё поспорить, то насчёт производительности — нет. Попробуете сделать пару тестов, прежде чем напугать меня (и других) такими «непонятыми» словами.
Готовый тест: jsperf.com/my-js-patty
Готовый тест: jsperf.com/my-js-patty
Мне это обсуждение очень напоминило обсуждения «оптимизаций» php-кода с заменой двойных кавычек на одинарные. :)
Да сто раз наплевать, пока профайлер не укажет, что это узкое место.
Да сто раз наплевать, пока профайлер не укажет, что это узкое место.
Я вроде про буфер уже говорил. Не надо в меня тестами кидаться. Вы суть то не уловили:
в данном примере, происходит инкремент html одного элемента, основанный всего лишь на индексе, не требующий дополнительных вычислений, требующих семантически выделить инкремент (конкатенацию) в блок действий for, а не в блок инициализации.
Смысл моего примера в том, что напрямую связанное с инкрементом единичное действие нефиг выделять в блок выполнения. Ему очень комфортно в итераторе. (проверьте тем же тестом)
Добавьте ваш семантически мусорный буфер в мой код и запустите тот же тест. Теперь мой код быстрее.
На реальной производительности (где на DOM куча вочеров, стилей, событий) наличие буфера никак не сказывается. А вот на «засорение» — да.
И вот пишут мне потом такие «спичечные» оптимизаторы: «посмотри ка мой код, что-то у меня не пойму все зависает после 15 минут работы, хотя везде все оптимизировано». Хотя не привыкать ловить минусы от непонимающих. Уже даже приятно как-то.
в данном примере, происходит инкремент 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 пункт?
Понимаю, что перевод, но…
17-й совет звучит неубедительно. Есть же ASI, являющейся частью спецификации ECMAScript. Слепо надеяться на точки с запятой тоже опасно.
Код ниже:
Ничего не вернет, ибо вступает в дело ASI.
Вместо того что-бы давать необоснованные, а порой, и вредные советы, лучше бы разжевали как работает ASI.
Я считаю что наличие точек с запятой или их отсутствие должно относиться к coding style guidelines в рамках проекта или компании, но не более. Это не правило языка программирования.
Дока: www.ecma-international.org/ecma-262/5.1/#sec-7.9
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, это должно быть обязательным.
Это не должно относиться к coding style, это должно быть обязательным.
Ваше «ой, если мы введём обязательные точки с запятыми, бедные веб-мастера удавятся от столь сложного синтаксиса», конечно же, убедительнее спецификации языка :)
Какая связь между убедительностью моих слов и убедительностью спецификации?
Основа современной спецификации писалась в тех же 90-х исходя из задач, которые тогда возлагались на язык.
Одна из задач — сделать язык как можно проще для простых смертных.
И эта часть спецификации является прямым следствием этого.
Основа современной спецификации писалась в тех же 90-х исходя из задач, которые тогда возлагались на язык.
Одна из задач — сделать язык как можно проще для простых смертных.
И эта часть спецификации является прямым следствием этого.
Я веду к тому, что в книгах и рекомендациях лучше объяснять, как работает на самом деле, а не как нравится лектору или писателю учебника. Ставить или не ставить точку с запятой это вопрос сугубо холиварный и не более. Правильно написанная программа работает и так и этак. Поэтому точкам с запятой место в coding style guidelines и я не согласен с вашей фразой:
Оно будет обязательным только тогда, когда будут (хотя маловероятно) внесены в спецификацию соответствующие изменения.
Это не должно относиться к coding style, это должно быть обязательным.
Оно будет обязательным только тогда, когда будут (хотя маловероятно) внесены в спецификацию соответствующие изменения.
with, eval и неявное определение глобальных переменных тоже часть спецификации.
Можно обойтись без любого из представленных здесь пунктов и шансы написать работающую программу всё равно остаются.
Этоже статья не про то, что у вас без этого не будет запускаться скрипт. Это статья про то, как не быть маргиналом в мире js. Как писать более-менее сложные программы с тем, чтобы если кто-то читал ваш код, он не испытывал брезгливости.
Можно обойтись без любого из представленных здесь пунктов и шансы написать работающую программу всё равно остаются.
Этоже статья не про то, что у вас без этого не будет запускаться скрипт. Это статья про то, как не быть маргиналом в мире js. Как писать более-менее сложные программы с тем, чтобы если кто-то читал ваш код, он не испытывал брезгливости.
Я понял вашу точку зрения. Но не могу согласиться с тем, что наличие или отсутствие точек с запятой (про with и eval я не говорю) является признаком говнокодерства. Есть прекрасные примеры из open source, с очень большим количеством коммиттеров, где в style guidelines точки с запятой убраны.
Я только один действительно популярный пример знаю.
С участием автора сего зафиксирован медицинский факт: освоение ASI может привести к распуханию ЧСВ. :)
С участием автора сего зафиксирован медицинский факт: освоение ASI может привести к распуханию ЧСВ. :)
Соглашусь, что примеров таких репозиториев мало, но я знаю еще несколько. От достаточно авторитетного и не такого «ЧСВ-шного» как fat человека. Один из его нескольких: github.com/isaacs/npm. Причем в некоторых своих репах он использует точки с запятой. Ну и его мнение по этому вопросу: blog.izs.me/post/2353458699/an-open-letter-to-javascript-leaders-regarding
7. Нативное vs ненативное здесь не причём. Массив всё равно в цикле собирать придётся. Здесь просто нужно понимать, как строки внутри устроены.
UFO just landed and posted this here
Крокфорд ок. Меня очень раздражает node.js-like отступы в 2 пробела.
И как я уже писал IE7 не умеет JSON.Parse.
Если шестерку уже никто не поддерживает, то заказчики иногда требуют поддержки оного.
И как я уже писал 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
UFO just landed and posted this here
github.com/search?q=json.stringify&ref=commandbar&type=Code
We've found 1,024,674 code results
We've found 1,024,674 code results
Есть рынки, на которых доля покупок через ИЕ7 достигает 30%. JSON.Parse тут самое то
Доля даже IE6 не смешна, к сожалению, а доверять нельзя даже данным, пришедшим со своего домена :)
Но я за jQuery.parseJSON, да, там как раз eval с предварительным тестированием, если JSON.parse нет в системе.
Но я за jQuery.parseJSON, да, там как раз eval с предварительным тестированием, если JSON.parse нет в системе.
А чем плохи 2 пробела?
Читабельность хуже. 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
gist.github.com/isaacs/357981 хорошая дискуссия по этому поводу.
Спасибо, хорошая ссылка. Наглядно указали на некоторые плюсы и минусы такого стиля (comma-first и dot-first). В этой дискуссии обсуждают только JS, но мне довелось повстречаться в различных проектах с такой нотацией и в других языках. Иногда попадались интересные решения в стилях.
Я считаю, что очень важно что бы в проекте стиль был единым, а какой стиль выбран для проекта — не такой важный вопрос. IDE можно настраивать под стили и нотации каждого отдельного проекта, а глаз программиста достаточно легко перестраивается.
Я считаю, что очень важно что бы в проекте стиль был единым, а какой стиль выбран для проекта — не такой важный вопрос. IDE можно настраивать под стили и нотации каждого отдельного проекта, а глаз программиста достаточно легко перестраивается.
Не стал бы такое делать в JavaScript из-за автоматической вставки точки с запятой. Уже напоролся на
return
[], теперь стараюсь заранее указывать языку, что дальше не конец выражения.
return
[], теперь стараюсь заранее указывать языку, что дальше не конец выражения.
Популряный совет «используйте jslint.com» весьма уныл с практической точки зрения. Вы правда думаете что кто-то ходит на регулярной основе на этот сайт и проверяет каждый свой коммит в JS там? Все такие вещи должны а) уметь быть запущенными локально б) прикручены к CI. Исключение может быть только если вы один в команде и делаете два коммита в год в js-файлы.
На самом деле из совета на эту тему — лучше сделайте npm install jshint Он как минимум «из коробки» куда более лояльный и практически применимый.
На самом деле из совета на эту тему — лучше сделайте npm install jshint Он как минимум «из коробки» куда более лояльный и практически применимый.
в 18 пункте более «элегантная» форма записи выглядит довольно устрашающе. Тут наверное наоборот лучше полагаться на то что — не стоит писать длинных строк которые затрудняют восприятие кода.
И в примере выше (тот же 18 пункт) пропущена скобка: «if(object.hasOwnProperty(key)) {».
И в примере выше (тот же 18 пункт) пропущена скобка: «if(object.hasOwnProperty(key)) {».
Давным-давно это не было редкой практикой использования аттрибута language у тега script.
Атрибут type=«text/javascript» тоже можно смело убирать.
Хорошее исследование на тему:
stackoverflow.com/a/2706364
stackoverflow.com/a/2706364
У Ильи Кантора встречается более элегантная форма записи
for(prop in object) if (object.hasOwnProperty(prop)) { //... }
но честно говоря я не уверен какие браузеры могут корректно обрабатывать ее.
Прим. пер.
Ведь все браузеры корректно могут, это ведь не специфическая конструкция, это просто
for (var prop in object)
if (object.hasOwnProperty(prop)) {
//...
}
Object.hasOwnProperty
есть во всех актуальных браузерах и даже в старых IE (начиная с 5.5).На самом деле, казалось бы, всего лишь убран перенос строки, но код уже не кажется таким загроможденным. Вроде бы и просто догадаться, но как-то не думалось, что это на самом деле неплохое решение )
В названии забыли словосочетание «для начинающих» — в оригинале «24 JavaScript Best Practices for Beginners».
Статья действительно для начинающих разработчиков. Половина советов в стиле «Капитана Очевидность».
Но больше всего убил совет №2 «Eval = Bad». Это извращённое и неверное представление об eval.
Во-первых, eval всего лишь в 4 раза медленнее apply или call, но гораздо быстрее всех остальных методов. При этом замечание глупое, т.к. разности в скорости между методами для конечного пользователя не заметны.
Во-вторых, eval не угрожает безопасности приложения. Безопасности приложения угрожает отсутствие проверки данных на сервере.
Из-за этого тупого утверждения «Eval = Bad» большая часть приложений используют воистину извращённые способы выполнения кода на клиенте, но по сути те же eval.
Статья действительно для начинающих разработчиков. Половина советов в стиле «Капитана Очевидность».
Но больше всего убил совет №2 «Eval = Bad». Это извращённое и неверное представление об eval.
Во-первых, eval всего лишь в 4 раза медленнее apply или call, но гораздо быстрее всех остальных методов. При этом замечание глупое, т.к. разности в скорости между методами для конечного пользователя не заметны.
Во-вторых, eval не угрожает безопасности приложения. Безопасности приложения угрожает отсутствие проверки данных на сервере.
Из-за этого тупого утверждения «Eval = Bad» большая часть приложений используют воистину извращённые способы выполнения кода на клиенте, но по сути те же eval.
Когда говорят что eval is evil, имеется в виду, что в большинстве случаев он не нужен и поэтому стоит подумать над альтернативными вариантами. Конечно, бывает, что он просто необходим.
Это лишь признак непонимания разработчиков сути утверждения eval is evil. Так как под eval имеются в виду исполнение стороннего кода вообще, любыми способами.
Из-за этого тупого утверждения «Eval = Bad» большая часть приложений используют воистину извращённые способы выполнения кода на клиенте, но по сути те же eval.
Это лишь признак непонимания разработчиков сути утверждения eval is evil. Так как под eval имеются в виду исполнение стороннего кода вообще, любыми способами.
Eval плох, если в него вставлять пользовательские данные, а если собирать функцию «из кирпичиков» для оптимизации (JIT-компиляции в JS, например), то очень даже полезен. Но лучше не eval тогда, а new Function.
4. Используйте JS Lint
Перефразировал бы как «НЕ используйте JS Lint») долго сидел на нем и следовал фанатично всем мелочам. По факту — это того не стоит. Используйте JSHint.
Отдельно хочется заметить, что многие из приведенных примеров JS Lint бы не прошли)
спасибо, ностальгия
А еще можно так:
void function(){
}();
void function(){
}();
UFO just landed and posted this here
Насчет точек с запятой — регулярно встречаю этот совет от Кроуфорда и прочих, плюс его JSLint на это ругается.
Я встречал на практике только одну реальную проблему с этим делом — когда между return и значением ставится перенос строки. Обязательная точка с запятой проблему эту не решает. Эта проблема решается повсеместными египетскими скобками.
Я видел только один пример, где пропущенная точка с запятой может принести проблемы:
var x = 2
[1,2,3].map(function() { console.log(x); })
Может кто еще привести каких-нибудь, поближе к практике?
Вообще я считаю что тема слишком раздута — я писал и с точками с запятой, и без них, и ни разу не налетал ни на какие проблемы.
Я встречал на практике только одну реальную проблему с этим делом — когда между return и значением ставится перенос строки. Обязательная точка с запятой проблему эту не решает. Эта проблема решается повсеместными египетскими скобками.
Я видел только один пример, где пропущенная точка с запятой может принести проблемы:
var x = 2
[1,2,3].map(function() { console.log(x); })
Может кто еще привести каких-нибудь, поближе к практике?
Вообще я считаю что тема слишком раздута — я писал и с точками с запятой, и без них, и ни разу не налетал ни на какие проблемы.
Читал, что если загнать код без точек с запятой в Google Closure Compiler например, то могут возникнуть проблемы. Т.е. при минификации/обфускации кода.
Я встречал на практике только одну реальную проблему с этим делом — когда между return и значением ставится перенос строки. Обязательная точка с запятой проблему эту не решает. Эта проблема решается повсеместными египетскими скобками.
Как раз попросили обратить внимание на ASI ссылку на который я добавил.
===
6. Объявляйте переменные для вне циклов
===
Не сразу сообразил, к чему там «для» ))
6. Объявляйте переменные для вне циклов
===
Не сразу сообразил, к чему там «для» ))
для тех, кто часто работает с DOM'ом, добавляет что-то на страницу, в цикле например, то используйте
document.createDocumentFragment()
добавляйте в цикле в него то что необходимо, и потом уже делайте 1 раз append этого фрагмента куда надо на странице, сэкономите на перерисовке 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) и туда зашить логику… Хм… Пойду вкоммичу.
Я раньше тоже не мог без комментариев. Но попробовав без них в js теперь не могу себя заставить заставить сделать огромную функцию с кучей действий в других языках. Если функция делает две вещи — значит вам нужны две функции :)
Есть несколько вещей, для которых все еще допустим использовать комментарии с моей точки зрения:
1. описание зудобробильных регулярок
2. пометка регрессионных unit-test'ов номером задачи из баг-трекера
3. Странные действия. Например, в каком-то тесте, в отличии от десятка других, мы проверяем свойства расписания не понедельника, а вторника. Полезно написать, что это сделано потому, что во вторник поезда выбранного направления, например, на мойке :) Хотя, даже это можно инкапсулировать в getTestWeekdayForTrainById(trainId) и туда зашить логику… Хм… Пойду вкоммичу.
Что такое функции замыкания?
автор имел ввиду вложенные функции (которые, кстати, не всегда являются замыканиями)
я обычно оформляю подобные вещи таким образом:
это облегчает чтение — когда видиш return, сразу становится ясно, что дальше никакого кода не выполнится.
function main(){
//...
doSomething();
//...
return;
function doSomething(){
//...
}
}
это облегчает чтение — когда видиш return, сразу становится ясно, что дальше никакого кода не выполнится.
почитайте про рефакторинг. один из основных запашков кода — это длинный метод.
Вы считаете, что поменять название функции, если код в ней поменял свою суть никто не забывает и это проще, чем поменять комментарий?
А если подобный код, который продемонстрировал Azy, нужно выполнить в большом количестве итераций? Тут можно слегка сэкономить — не производя лишних вызовов функций (а иногда и в определении функций).
// Create font
...
// Draw rectangle
...
А если подобный код, который продемонстрировал Azy, нужно выполнить в большом количестве итераций? Тут можно слегка сэкономить — не производя лишних вызовов функций (а иногда и в определении функций).
поддерживаю. капитанские комментарии — зло. потому как часто случается, что код обновили — а комментарии нет.
Пишу сложный большой проект.
Комментарии в виде API документации (типа JSDoc) хорошая штука (да и решают все таки другую задачу)
Во всех остальных случаях: хочешь вставить комментарий, значит код написан криво и надо рефакторить.
Комментарии в виде 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)
А вообще, всем советую свежую книжку Effective JS Дэвида Хермана, очень неплохо объяснены прототипы, например (http://www.amazon.com/gp/product/B00AC1RP14/ref=oh_d__o00_details_o00__i00?ie=UTF8&psc=1)
Автор кода из пункта 7 не подозревает о существовании пустых массивов.
Вы так говорите, как будто с for в том же случае не надо проверять на непустоту. Не о том же речь.
Не надо. Зачем? Вариант с for'ом тем и хорош, что там всё естественным образом получается без дополнительных проверок, а вот вариант с join или будет производить неожидаемый результат, или будет нечитаемым (для инетерса попробуйте реализовать его таким образом, чтобы в случае нуля элементов возвращался пустой ul)
Речь о том, что автор говорит, что for можно заменить функциями для работы с массивами и сам же приводит пример, который не будет эквивалентен коду с for'ом.
Как по мне, так яблоки нужно сравнивать с яблоками.
Не о том же речь.
Речь о том, что автор говорит, что for можно заменить функциями для работы с массивами и сам же приводит пример, который не будет эквивалентен коду с for'ом.
Как по мне, так яблоки нужно сравнивать с яблоками.
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
У Ильи Кантора встречается более элегантная форма записи
И пишите свои посты, чтобы «был торт»
Имелись в в виду функции прототипов.
и вообще, если ваш объект приходится часто листать, то лучше установить его свойства с помощью defineProperty, чтоб ненужные свойства были not-enumerable
Можно кратко почитать статью, а можно просто почитать две полезные книги (вне зависимости от того, пишешь код на JavaScript, TypeScript или JavaScript) — Javascript: Good Parts и Javascript: Templates. (=
Воспользуйтесь прогрессивным улучшением (progressive enchantment)
Шутка, или опечатка по Фрейду? Мне понравилось ;)
Ещё по теме — Airbnb JavaScript Style Guide. Не думаю, что я полностью согласен со всеми пунктами, изложенными там, но в любом случае материал полезный и по текущей теме.
Sign up to leave a comment.
24 совета javascript-разработчику