Comments 88
Много раз встречал, что народ наплевательски относится к глобальному контексту и временные переменные утекают из разных мест.
Я, лично, всегда проверяю, а не появилось ли чего нового там, чего не должно быть. Пока вручную, но т.к. уже несколько раз приходилось перелапачивать исходники (~400 js файлов), в поисках места с косяком, то планирую это дело автоматизировать.
Я, лично, всегда проверяю, а не появилось ли чего нового там, чего не должно быть. Пока вручную, но т.к. уже несколько раз приходилось перелапачивать исходники (~400 js файлов), в поисках места с косяком, то планирую это дело автоматизировать.
По-моему все IDE, с которыми я работал (Eclipse, IntelliJ IDEA, NetBeans), выводят предупреждение, если попытаться инициализировать переменную без var. Вообще было бы неплохо pre-commit хук поставить на контроль версий, чтобы не давало даже такую ересь коммитить.
и что даст хука? а если используется переменная, определенная в вызывающем контексте и тот контекст может быть далеко не window…
Intellij IDEA понимает scope и не ругается, когда используется переменная, определённая выше. И не нужен SoffeeScript.
IDEA так же отличает глобальную область видимости от scope функций. Другими словами, если Вы напишите в файле first.js:
или так:
То в файле second.js не будет предупреждений при обращении к этой переменной (если он в том же проекте).
Либо JSLint, тут кому что больше нравится, инструментов хватает.
IDEA так же отличает глобальную область видимости от scope функций. Другими словами, если Вы напишите в файле first.js:
var global = {}; // В глобальном контексте
или так:
window.global = {};
То в файле second.js не будет предупреждений при обращении к этой переменной (если он в том же проекте).
Либо JSLint, тут кому что больше нравится, инструментов хватает.
как минимум ide рисуют такие переменные другим цветом
А синтаксический сахар типа CoffeeScript не пробовали? Он должен избавлять от многих бед. В Rails 3.1 используется по умолчанию.
Автору оригинальной заметки наверняка бы помогло.
Если кодить в WebStorm, то пропустить var практически невозможно. Переменные без var очень броско выделяются в коде: подчеркиваются голубым зигзагом, а их фон заливается примерно таким цветом
#F0F0E7
. Думаю, и другие редакторы такое умеют.Сейчас вам, автор, напишут, что программисты никогда не должны ошибаться. И вообще что вы — лох и посмели посягнуть на святыню (node.js). А сам JS — великолепный язык, на котором прекрасно пишутся крупные приложения, просто вы не умеете его готовить.
Дак перевод же.
Вообще-то, JS — действительно великолепный язык. Его только подчистить от ошибок молодости надо (и этих ошибок не так много)
А можно огласить Ваш список? Хочу сверить со своим…
Исправить:
— По умолчанию глобальный контекст переменных
— Function-scope (хотелось бы block-scope)
— Semicolon insertion
Добавить:
— модульность
И уже можно пользоваться.
Что-то еще было, только ща котелок не варит уже :)
— По умолчанию глобальный контекст переменных
— Function-scope (хотелось бы block-scope)
— Semicolon insertion
Добавить:
— модульность
И уже можно пользоваться.
Что-то еще было, только ща котелок не варит уже :)
Мой шире… Еще заменить прототипное ООП на классовое и выкосить неявное приведение типов, а с ним все приколы с "==".
> Еще заменить прототипное ООП на классовое
А, ну я этого ожидал. почему-то всем в обязательном порядке хочется втянуть C++-style OOP за уши в любой язык.
Не нужно никакого «классового ООП» в JS.
> выкосить неявное приведение типов, а с ним все приколы с "==".
Да, согласен. Строгая типизация не помешала бы
А, ну я этого ожидал. почему-то всем в обязательном порядке хочется втянуть C++-style OOP за уши в любой язык.
Не нужно никакого «классового ООП» в JS.
> выкосить неявное приведение типов, а с ним все приколы с "==".
Да, согласен. Строгая типизация не помешала бы
> Не нужно никакого «классового ООП» в JS.
Можно спорить долго, но факт остаётся фактом: JS — единственный популярный язык с ООП на прототипах, да и в нем в конечном итоге все ваяют классы поверх прототипов а дальше по старинке.
Можно спорить долго, но факт остаётся фактом: JS — единственный популярный язык с ООП на прототипах, да и в нем в конечном итоге все ваяют классы поверх прототипов а дальше по старинке.
> JS — единственный популярный язык с ООП на прототипах, да и в нем в конечном итоге все ваяют классы поверх прототипов а дальше по старинке.
Поэтому не надл натягивать на язык то, для чего он не создавался, а обучать программистов действовать не по старинке ;)
Поэтому не надл натягивать на язык то, для чего он не создавался, а обучать программистов действовать не по старинке ;)
И реально кого-то удалось обучить не действовать по старинке?
Удавалось конечно. Какой это программист, если он не способен обучиться чему-то новому? ;)
Более того, большинство современных фреймворков для JS, даже те, которые натягивают способы работы «по старинке» совсем не чураются использовать prototype-based OOP, и их внутренности очень интересны для его изучения.
Более того, большинство современных фреймворков для JS, даже те, которые натягивают способы работы «по старинке» совсем не чураются использовать prototype-based OOP, и их внутренности очень интересны для его изучения.
> Поэтому не надл натягивать на язык то, для чего он не создавался
Все так на полном серьёзе считают прототипы обдуманным решением. Интересно, если на начальную версию языка понадобилось 10 дней, то сколько времени было потрачено на предварительное обдумывание и проектирование?
Все так на полном серьёзе считают прототипы обдуманным решением. Интересно, если на начальную версию языка понадобилось 10 дней, то сколько времени было потрачено на предварительное обдумывание и проектирование?
То, что на начальную версию языка пондобилось 10 дней, ничего не говорит о качестве обдумывания и проектирования — это раз. Вообще-то, ошибок в языке достаточно мало. Можно посмотреть, что об этом говорит сам автор языка, например.
Во-вторых — JS — это, по сути, Self+Scheme с C-like синтаксисом и это очень хорошо. То, что вы не представляете себе другого ООП, кроме C++ного, не значит, что этот ООП надо натягивать на все языки ;)
Ну и в третьих, Harmony добавит достаточно много вкусного сахара и попытается исправить некоторые из ошибок молодости.
Во-вторых — JS — это, по сути, Self+Scheme с C-like синтаксисом и это очень хорошо. То, что вы не представляете себе другого ООП, кроме C++ного, не значит, что этот ООП надо натягивать на все языки ;)
Ну и в третьих, Harmony добавит достаточно много вкусного сахара и попытается исправить некоторые из ошибок молодости.
> ничего не говорит о качестве обдумывания и проектирования — это раз
… и тайком протащить туда его спасительные фишки: first class functions (замыкания сделал позже, но они были частью плана сразу) и прототипы (примерно как в языке Self).
И?
Цитата как бы намекает на широту и продолжительность обсуждения этого элемента дизайна языка Javascript.
Ни на что она не намекает. То, что автор пошел против желания руководства, никак не указывает на то, что он не думал перед тем, как вводить эту функциональность.
В итоге JS — самый популярныя функциональный язык программирования в мире, но, как всегда
В итоге JS — самый популярныя функциональный язык программирования в мире, но, как всегда
Действительно, зачем создавать продукт здесь и сейчас, зачем думать о бизнес задачах, зачем захватывать не занятые пока еще рынки? Зачем думать о рынке труда и текущих знаниях большинства программистов? Нет! Лучше писать код, не поднимая головы, и не интересуясь ничем больше. И вместо основ экономики, например, выучивать как делать ООП на прототипах.
единственный популярный язык с ООП на прототипах
Не единственный, на вскидку:
* Ruby (появился раньше, чем js)
* ActionScript 3 (близкий родственничек)
У этих двух реализация наследования сделана на порядок удобнее (т.е. я бы сказал, она там есть из коробки). Это на мой взгляд, конечно. Всегда найдутся фанаты десятка различных сторонних реализаций наследования в чистом js (и ни одного стандартного способа в одну понятную всем строку, господа, ни одного!).
В Ruby не prototype-based ООП (емнип)
ActionScript — это не близкий родственник, а младший брат, выросший из Javascript -> Ecmascript
ActionScript — это не близкий родственник, а младший брат, выросший из Javascript -> Ecmascript
В Ruby очень интересная реализация, я привык ее считать прототипориентированной, но возможно, я ошибаюсь.
В двух строчках описать сложно, но попробую:
1) В руби нет понятия чисто-класс как шаблон (как в C++), в Руби все классы точно такие объекты, как и объекты.
2) Method lookup использует цепочки «прототипов», очень приближенно говоря, у каждого объекта есть пару цепочек, указывающих на предков, к примеру цепочки class и superclass. Кратко можно глянуть в документации www.ruby-doc.org/core-1.9.3/Class.html#method-i-superclass
Это позволяет расширять классы как угодно, во всех старых инстансах класса будут доступны новые методы. Чем не прототипы?
3) Есть возможность клонировать объекты, а так же вы вольны:
* создавать новые объекты, выдергивая уже готовые методы из существующих (Через Method#unbind)
* создавать классы в рантайме, например используя некую функцию
* расширять только конкретные объекты, не трогая остальные объекты этого класса.
и т.д.
* пройти всю цепочку предков и что-то сделать с каждым.
Ну есть хочется вообще чего-то особо извращенного, типа смены class у созданного инстанса, то можно попробовать www.ruby-doc.org/stdlib-1.9.3/libdoc/delegate/rdoc/Delegator.html#method-c-new
Ну младший брат это и есть близкий родственник, как я думаю :) Мне кажется, в AS3 есть интересные решения (смешать Java и JS и не взбалтывать).
В двух строчках описать сложно, но попробую:
1) В руби нет понятия чисто-класс как шаблон (как в C++), в Руби все классы точно такие объекты, как и объекты.
2) Method lookup использует цепочки «прототипов», очень приближенно говоря, у каждого объекта есть пару цепочек, указывающих на предков, к примеру цепочки class и superclass. Кратко можно глянуть в документации www.ruby-doc.org/core-1.9.3/Class.html#method-i-superclass
Это позволяет расширять классы как угодно, во всех старых инстансах класса будут доступны новые методы. Чем не прототипы?
3) Есть возможность клонировать объекты, а так же вы вольны:
* создавать новые объекты, выдергивая уже готовые методы из существующих (Через Method#unbind)
* создавать классы в рантайме, например используя некую функцию
* расширять только конкретные объекты, не трогая остальные объекты этого класса.
и т.д.
* пройти всю цепочку предков и что-то сделать с каждым.
Ну есть хочется вообще чего-то особо извращенного, типа смены class у созданного инстанса, то можно попробовать www.ruby-doc.org/stdlib-1.9.3/libdoc/delegate/rdoc/Delegator.html#method-c-new
это не близкий родственник, а младший брат, выросший из Javascript -> Ecmascript
Ну младший брат это и есть близкий родственник, как я думаю :) Мне кажется, в AS3 есть интересные решения (смешать Java и JS и не взбалтывать).
Вот чуть более наглядная презентация по теме
www.slideshare.net/burkelibbey/rubys-object-model-metaprogramming-and-other-magic
www.slideshare.net/burkelibbey/rubys-object-model-metaprogramming-and-other-magic
То, что вы описываете у Ruby — это метаобъекты, а не прототипное наследование. В первом случае у нас есть чертежи объектов — метаклассы, и есть изготовленные по чертежам объекты. Во втором случае любой объект можно превратить в шаблон класса. Разница как между промышленной сборкой и размножением живых организмов ;)
> Ruby
И где там прототипы?
> ActionScript 3
Так они же еще в версии 2 вроде перешли на классы, нет?
И где там прототипы?
> ActionScript 3
Так они же еще в версии 2 вроде перешли на классы, нет?
> Так они же еще в версии 2 вроде перешли на классы, нет?
Это банальный сахар поверх prototype-based OO, что и неудивительно, ведь ActionScript растет из ECMAScript.
help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f3f.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7fa3
Это банальный сахар поверх prototype-based OO, что и неудивительно, ведь ActionScript растет из ECMAScript.
help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f3f.html#WS5b3ccc516d4fbf351e63e3d118a9b90204-7fa3
Не совсем. В 2 и тем более 3 версии прототипы — не более чем implementation details. Это к тому, что сахар — это факультативное удобство — (хочешь — используй, хочешь — нет), а классы в AS2 и AS3 — это более-менее обязательное требование.
В AS2 классы были реализованы поверх прототипного наследования и при компиляции код неявно преобразовывался из class-based в prototype-based.
О чём, кстати, упоминается в статье по вами приведённой ссылке:
Для AS3 была написана новая виртуальная машина, названная AVM2 и там уже реализовано честное class-based ООП. Хотя и оставлена опциональная возможность динамической декларации полей и методов.
О чём, кстати, упоминается в статье по вами приведённой ссылке:
It’s important to understand that the underlying inheritance mechanism did not change between ActionScript 1.0 and ActionScript 2.0. ActionScript 2.0 merely added a new syntax for defining classes. The prototype chain works the same way in both versions of the language.
Для AS3 была написана новая виртуальная машина, названная AVM2 и там уже реализовано честное class-based ООП. Хотя и оставлена опциональная возможность динамической декларации полей и методов.
В защиту JS хотел бы сказать, что он позволяет написать свою реализацию примесей и наследования, с которой было бы удобно работать, хороший пример, на мой взгляд, в AtomJS: github.com/theshock/atomjs/blob/master/Docs/Class/Class.md
Опять же, это означает, что нужно тащить дополнительные соглашения в код. Сравните:
Ruby
JS + SomeFramework
И начинается. А что во втором примере будет, если будет вызов
И, внезапно, все подобные проблемы сваливаются на голову разработчика (и пользователей) фреймворка, а не на рантайм языка, как должно было бы по хорошему.
Опять же, это означает, что нужно тащить дополнительные соглашения в код. Сравните:
Ruby
class GameObject; end
module Jump; end
module Run; end
class DuckFromMario < GameObject
include Run, Jump, Fire
end
duck1 = DuckFromMario.new
JS + SomeFramework
var Run = SomeFramework.createClass({
__constructor__: function(){}
});
var Jump = SomeFramework.createClass({
__constructor__: function(){}
});
var Fire = ...
var GameObject = SomeFramework.createClass({
__constructor__: function(name) {},
});
var DuckFromMario = SomeFramework.createClass({
__constructor__: function(name) {},
__extends__: GameObject,
__include__: [Run, Jump, Fire],
....
});
var someDuck = new DuckFromMario("someDuck")
И начинается. А что во втором примере будет, если будет вызов
var someDuck = DuckFromMario()
, подумал ли автор фреймворка об этом?var DuckFromMario = SomeFramework.createClass({
__constructor__: function(name) {},
//а что будет, если конструктор будет без параметра? А как же родитель?
// а что будет если конструктора не будет вообще?
И, внезапно, все подобные проблемы сваливаются на голову разработчика (и пользователей) фреймворка, а не на рантайм языка, как должно было бы по хорошему.
> И, внезапно, все подобные проблемы сваливаются на голову разработчика (и пользователей) фреймворка, а не на рантайм языка, как должно было бы по хорошему.
Потому что не надо натягивать C++-like OOP на язык с совершенно другим OOP.
Потому что не надо натягивать C++-like OOP на язык с совершенно другим OOP.
Советую посмотреть видео с YUIConf 2011 «From one, many; from many, one — class inheritance and composition in YUI, Luke Smith», когда его выложат в YUI theater.
murr правильно говорит, было бы лучше еслиб всё это было в языке, а не фрэймворках. И все кто это делает отлично разбираются в жаваскриптовом ООП, и к счастью не только в нём.
murr правильно говорит, было бы лучше еслиб всё это было в языке, а не фрэймворках. И все кто это делает отлично разбираются в жаваскриптовом ООП, и к счастью не только в нём.
> хороший пример, на мой взгляд, в AtomJS: github.com/theshock/atomjs/blob/master/Docs/Class/Class.md
Отлично, еще один пример в мою копилку.
> И, внезапно, все подобные проблемы сваливаются на голову разработчика (и пользователей) фреймворка, а не на рантайм языка, как должно было бы по хорошему.
Именно.
Отлично, еще один пример в мою копилку.
> И, внезапно, все подобные проблемы сваливаются на голову разработчика (и пользователей) фреймворка, а не на рантайм языка, как должно было бы по хорошему.
Именно.
И начинается. А что во втором примере будет, если будет вызов
var someDuck = DuckFromMario()
, подумал ли автор фреймворка об этом?
Между прочим, это очень интересная возможность. Как разница между
var n = new Number( '15' );
и
var n = Number( '15' );
//а что будет, если конструктор будет без параметра? А как же родитель?
И что?
Lua, и если он не популярен в вебе то это не значит что он не популярен.
Пишите на Haskell, там не ошибетесь :)
? Неужто то, что я пропустил один var делает меня ущербным?
— Что может быть хуже, чем откусить яблоко и обнаружить там червяка?
— Откусить яблоко и обнаружить там полчервяка!
А по-моему такие цейтноты очень интересны. Концентрация 200%!
— Что может быть хуже, чем откусить яблоко и обнаружить там червяка?
— Откусить яблоко и обнаружить там полчервяка!
А по-моему такие цейтноты очень интересны. Концентрация 200%!
Есть отличная штука, которая помогает отловить неопознанные глобальные переменные – detect-global, но она не сгодится для server-side в текущей реализации.
Недавно начал работать с Javascript'ом. Пишу в строго настроенной WebStorm по TDD-методологии, без 'use strict' не обходится ни одна функция, весь код перепроверяю через jslint. Для меня это пока минимальный набор методов, позволяющих хоть какой-то быть уверенным в своем js-коде. Поленился написать тесты — код ломается, поленился проверить jslint'ом — код ломается… это ужас какой-то! :)
Я бы назвал его недоделанным. Но при определенной дисциплине на нем можно писать работающий код.
У него есть плюс, который в значительной степени перекрывает все эти минусы: на нем можно написать приложение, которое будет работать на большинстве платформ (с помощью браузера). Для меня это оказалось очень удобным. :)
У него есть плюс, который в значительной степени перекрывает все эти минусы: на нем можно написать приложение, которое будет работать на большинстве платформ (с помощью браузера). Для меня это оказалось очень удобным. :)
альтернатива?
TDD и статический анализ у нас теперь как БСДМ проходят?
Интересное кино!
Интересное кино!
Да, перед тем, как начинать реализовывать новую фичу или фиксить баги я разрабатываю тесты для как можно более полного покрытия. Иногда бывает под сотню тестов для очередной feature, для багов обычно меньше.
Если в результате доработок должны появиться новые методы, используемые в тестах, то перед написанием тестов создаются эти методы с пустыми телами. Позднее добавляется реализация.
Как результат — после того, как все тесты начинают проходить, я могу быть уверен, что задача выполнена.
На мой взгляд БСДМ — это попытка фиксить баги/добавлять функционал без предварительно написанных тестов.
Если в результате доработок должны появиться новые методы, используемые в тестах, то перед написанием тестов создаются эти методы с пустыми телами. Позднее добавляется реализация.
Как результат — после того, как все тесты начинают проходить, я могу быть уверен, что задача выполнена.
На мой взгляд БСДМ — это попытка фиксить баги/добавлять функционал без предварительно написанных тестов.
В том числе именно поэтому Гугл ваяет Dart на замену JS.
Зачем Гугл ваяет Дарт, не знает, похоже, даже сам Гугл
Тем, кто меня минусует, советую почитать вот эту статью: blogs.perl.org/users/rafael_garcia-suarez/2011/10/why-dart-is-not-the-language-of-the-future.html
Тогда нужно прочитать и вот это — www.infoq.com/articles/google-dart
За что люблю Python — прострелить в нём ногу гораздо сложнее, обычно.
Всё-таки есть что-то нехорошее в том, что глобальные переменные делать легче, чем локальные.
Всё-таки есть что-то нехорошее в том, что глобальные переменные делать легче, чем локальные.
Поглядел MelonCard. Какой-то неимоверный треш. На любые данные сообщает, что нашел меня на тысячах сайтов.
Я как-то полночи отлаживал программу на C, которая вела себя примерно так же — половина данных правильная, половина нет. Оказалось, что под буфер из double-ов я выделял память как n*sizeof(char).
Дурацкую неотлавливаемую ошибку лёгким движением руки можно сделать в любом языке.
Дурацкую неотлавливаемую ошибку лёгким движением руки можно сделать в любом языке.
При современных IDE, которые все подчеркивают/подсвечивают/выделяет рамкой, подобные ошибки делать надо уметь.
С другой стороны, если писать код в 3-4 часа ночи — то подобные ошибки могут быть у любого профи.
С третьей стороны, нехватка тестов дала о себе знать, вот если бы было нагрузочное тестирование… Если я правильно все понял, то проблема проявлялась когда несколько пользователей одновременно совершали запросы, а юнит-тесты все проверки наверника выполняли в однопользователском режиме.
С другой стороны, если писать код в 3-4 часа ночи — то подобные ошибки могут быть у любого профи.
С третьей стороны, нехватка тестов дала о себе знать, вот если бы было нагрузочное тестирование… Если я правильно все понял, то проблема проявлялась когда несколько пользователей одновременно совершали запросы, а юнит-тесты все проверки наверника выполняли в однопользователском режиме.
просто нужно всегда писать var
думаю запрет использования глобального контекста (объявление переменных без var) должно ложится на сам интерпретатор/компилятор.
например в JScript.NET в параметрах компилятора существует опция fast, которая и так включена по-умолчанию.
так для кода
выдалась бы ошибка
причем во время компиляции, а в продакшене и при выполнении приложения
например в JScript.NET в параметрах компилятора существует опция fast, которая и так включена по-умолчанию.
так для кода
initial = extractVariables(req.body);
выдалась бы ошибка
error JS1135: Variable 'initial' has not been declared
причем во время компиляции, а в продакшене и при выполнении приложения
Сочувствую, отладка асинхронного кода и впрямь бывает болью в заднице.
«нужно было использовать CoffeeScript» мне захотелось написать сразу после прочтения заголовка :)
Удачи вам с проектом :)
«нужно было использовать CoffeeScript» мне захотелось написать сразу после прочтения заголовка :)
Удачи вам с проектом :)
Sign up to leave a comment.
Как пропущенный var сорвал наш запуск