LINUX.ORG.RU

за что мы любим javascript

 


0

1
for(var j = 0; j < 3; j++) {
  console.log('j1 %s', j)
  for(var j = 0; j < 3; j++) {
    console.log('j2 %s', j)
  }
}



результат

j1 0
j2 0
j2 1
j2 2


В общем то я уже давно знаю что javascript так не умеет. И когда встретил неожиданное поведение, наверное и минуты не потратил... но как то осадочек.

★★★★★

javascript так не умеет.

Ты вправе в любом языке применять конструкции не поназначению, ожидая от них поведения, которое они тебе ничем не обязаны предоставлять. Это вовсе не значит, что чего-то не умеет язык. Значит лишь то, что чего-то не умеешь ты.

Твое «неожиданное поведение» сравни

я передал два числа в функцию, возвращающую сумму чисел, и ожидал получить разницу, но получил сумму! какой кошмар

anonymous ()
Ответ на: комментарий от anonymous

и dib2 и ещё один анонимус.
Посыпаю голову, отстал от жизни на целое поколение браузеров. Или даже на два: яваскрипт из неюзабельного говна превратился в неюзабельное неизучаемое говно :) (три способа объявления?? var хотя бы устаревшим объявлен?).

Любопытно, а стрелку для анонимных функций уже можно без препроцессора пользовать (имея ввиду все современные браузеры, меньше года от роду)?
в смысле

( a => a + 1)
или как там оно

AndreyKl ★★★★★ ()
Последнее исправление: AndreyKl (всего исправлений: 2)
Ответ на: комментарий от AndreyKl

в неюзабельное неизучаемое говно

Спецификация языка занимает всего 20 параграфов. Странно считать себя программистом, неспособным осилить 100 страниц чего-то там, в то время когда спецки на какие-нибудь протоколы или API могут больше на порядки.

anonymous ()
Ответ на: комментарий от anonymous

гм, ну спецификация может и занимает 20 параграфов, я не читал, не знаю. Но зачем 3 способа объявления?

Тем более такой замечательный как var. Очень любопытен пример использования var. Особенно такой красивой возможности как в начальном сообщении. Не затруднит ли вас привести такой пример?

т.е. в целом я понимаю, что const это одно, а let другое. Но если let - это человеческий вар (идти читать лень), то для чего оставили var?

AndreyKl ★★★★★ ()
Последнее исправление: AndreyKl (всего исправлений: 3)
Ответ на: комментарий от AndreyKl

Да везде, где надо объявить новую переменную, вне блока кода. Попробуй объяви переменную из eval, например, с помощью let или const.

eval('let x = 100'); console.log(x) // exception
eval('var x = 100'); console.log(x) // 100

То же самое если ты работаешь с модулем vm в ноде, и вообще с вещами где есть динамический доступ к контекстам и областям видимости.

anonymous ()
Ответ на: комментарий от AndreyKl

На самом деле, способов объявления 4. Можно не в strict mode еще объявить глобальную переменную путем простого присваивания

a = 15

Другое дело, что при использовании любой современной фичи языка (классы, стрелочные функции и т.д.) интерпритатор JS автоматически перейдет в strict mode.

Объявление глобальных переменных таким образом, как и использование var считается все же deprecated. Использование eval и vm в ноде, как заметил аноним, все же очень нечастое явление и скорее является исключением. Для нормального современного кода var не используется

dr15 ()
Ответ на: комментарий от anonymous

eval('var x = 100'); console.log(x) // 100[

Это песец, если хочешь глобальную переменную — говори это явно (window.x/global.x/self.x в зависимости от того, что именно нужно).

x3al ★★★★★ ()
Последнее исправление: x3al (всего исправлений: 1)
Ответ на: комментарий от AndreyKl

Любопытно, а стрелку для анонимных функций уже можно без препроцессора пользовать

она не для анонимных функций а для функций без собственного контекста.

TDrive ★★★★★ ()
Ответ на: комментарий от TDrive

Тащемта, стрелочная функция не может иметь имени. Так что она вполне себе анонимна всегда.

x = function test() {
  return test; // вернет саму функцию и не будет произведен захват переменной x из внешнего скоупа
}

y = () => y; // вернет саму функцию, но захватит переменную из внешнего скоупа. 

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

anonymous ()

Я не стал заморачиваться и пишу на es6 с eslint, редактор там сам подскажет что хорошо что плохо. Также это способ узнать как писать что либо на js

Здесь про переменные и прочее подробно Основы ES6 https://www.youtube.com/playlist?list=PLqHlAwsJRxAOpWPtj2T6HhSzX-lKmKV2q

ism ★★ ()
Ответ на: комментарий от TDrive

ism.

По большому счёту мне не так важно что там. ие11 не поддерживает (стрелочку конкретно), а его ещё слишком много. Поэтому я глядеть что там к чему не полезу. Просто поднадоело писать function() {} когда можно просто () => {}.

Переходить на препроцессоры для себя смысла не вижу в связи с переездому на idris/haskell/elm/scala (в указанном порядке попытаюсь начиная с идрис).

Поэтому так досижу уже. За пояснения спасибо.

AndreyKl ★★★★★ ()
Последнее исправление: AndreyKl (всего исправлений: 3)
Ответ на: комментарий от grem

Видел, я уж лет 10 с этим чудом знаком, или 12. Года два назад задумался о переезде на какой нибудь препроцессор. Но сравнения и изыскания увели меня довольно далеко. Где то с пол года назад решил что это точно будет либо idris, либо haskell, либо elm, либо scala (указаны в порядке приоритета).

AndreyKl ★★★★★ ()
Последнее исправление: AndreyKl (всего исправлений: 1)
Ответ на: комментарий от dr15

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

AndreyKl ★★★★★ ()
Ответ на: комментарий от AndreyKl

Возьми eslint да настрой чтобы ругался на var, если так приперло. Хотя shadow variables он тебе тоже покажет.

Вылезай из чулана :). Яваскрипт конечно местами странный, но вовсе не теми местами про которые ты пишешь.

Vit ★★★★★ ()
Ответ на: комментарий от anonymous

Короче, всё что ты понаписал не делает javascript совместимым c псевдокодом или блок-схемами. А вот сишечка с кучей сайд-эффектов или питон - вполне совместимы. И да, ванильный javascript - как секс в гамаке и стоя. Можно, но не нужно.

Shadow ★★★★★ ()
Последнее исправление: Shadow (всего исправлений: 1)
Ответ на: комментарий от grem

Да, должен согласиться, никакого чуда, наверное большая часть динамически «типизированных» языков такая и есть, по крайней мере та с которой я знаком вроде вся такая. Одна малина.

Но правда с var яваскрипт кажется перещеголял всех. в php конечно тоже нельзя объявить локальную переменную внутри, скажем, цикла. Но - в php вообще нельзя объявить переменную. Поэтому недоразумений быть не может, если ты используешь переменную с тем же именем, значит это та же переменная. А вот поведение var мягко говоря немного неожиданно.

Но в целом да, пофиг. От этого ни жарко ни холодно, как был динамический язык так и остался, одним недостатком больше, одним меньше - по большому счёту ничего не меняется.

AndreyKl ★★★★★ ()
Ответ на: комментарий от Vit

но вовсе не теми местами про которые ты пишешь.

сначала пропустил твоё сообщение (как адекватное :) ), но вот что то прям сейчас удивился.

Скажи, ты действительно считаешь что при объявлении переменной в дочерней области видимости нормально что используется переменная из родительской?

Т.е. нет, не пойми меня не верно, я понимаю что объяснить можно всё. Но ты действительно считаешь что так _и_ _должно_ _быть_?

AndreyKl ★★★★★ ()
Ответ на: комментарий от AndreyKl

Никакого странного поведения нет. В JS оластью дейсвия var является функция, а не блок кода.

Твой пример можно было бы переписать так:

for(var j = 0; j < 3; j++) {
  console.log('j1 %s', j);

  (function() {
    for(var j = 0; j < 3; j++) {
      console.log('j2 %s', j)
    }
  })()

}
j1 0
j2 0
j2 1
j2 2
j1 1
j2 0
j2 1
j2 2
j1 2
j2 0
j2 1
j2 2

Для let и const действие распростарняется на блок кода

for(let j = 0; j < 3; j++) {
  console.log('j1 %s', j)
  for(let j = 0; j < 3; j++) {
    console.log('j2 %s', j)
  }
}

Никаких ошибок в реализации этого нет. Это просто особенность языка. Так его спроектировали.

Об этой особенности пишут во всех учебниках/мануалах при описании var жирным шрифтом и все равно люди набивают на нем шишики.

Если в одной функции есть переменная которая объявлена несколько раз со словом var, то второе и последующие определения var просто игнорируются

var a = 15
var a = a + 15
console.log(a)
30

На самом деле, в «старом» JS проблема придумывания уникальных счетчиков для циклов была практически единственной проблемой, связанной с этой особенностью var.

Остальные проблемы возникали реже.

Для борьбы с этим, юзай, как тебе уже советовали, линтеры и forEach для массивов (если он там есть). for in для массивов тоже косячный. В современных версиях юзай let и const и забуть о проблеме.

dr15 ()

И это не ошибка проектирования. Это вопрос перфоманса. Если бы var имел блочную область видимости, как теперь имеют let и const - это было бы лютым оверхедом для интерпретатора на тот момент, потому что на каждую область видимость создается объект. Это теперь можно это позволить и это ничего не стоит. Но не в 1995 году, в браузерном языке который был предназначен для анимации снежинок.

anonymous ()

В общем то я уже давно знаю что javascript так не умеет

ЯННП. Что значит не умеет? Чего не умеет? Может это ты чего-то не умеешь, например думать перед тем как пишешь?

PS: результат правильный и ожидаемый.

no-such-file ★★★★★ ()
Ответ на: комментарий от AndreyKl

Скажи, ты действительно считаешь что при объявлении переменной в дочерней области видимости нормально что используется переменная из родительской?

Нет. Но эта и многие другие «проблемы» давно решены. Ставишь линтер, чтобы ругался на всякую стрёмную фигню и пользуешься только нормальными фичами.

Vit ★★★★★ ()
Ответ на: комментарий от anonymous

В 1995 году все эти свистоперделки не были нужны никому.

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

TDrive ★★★★★ ()