Тонкие различия между JavaScript и Lua

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

Итак, недавно я играл с Lua через löve2d (приятно!) - и я думаю, что Lua тоже замечательный. Как я вижу, эти два языка очень похожи.

Существуют очевидные различия, такие как

  • Синтаксис
  • проблемный домен
  • библиотеки
  • типы (бит)

но которые более тонкие? Есть ли что-нибудь, что JavaScript-кодер считал бы само собой разумеющимся, что работает в Lua немного иначе? Есть ли какие-либо подводные камни, которые могут быть неочевидны для опытного кодера одного языка, пытающегося использовать другой?

Например: в Lua массивы и хэши не являются отдельными (есть только таблицы) - в JavaScript они представляют собой числовые массивы и хешированные объекты. Ну, это одна из наиболее очевидных различий.

Но существуют ли различия в переменной scope, неизменяемости или что-то вроде этого?

Ответ 1

Еще несколько отличий:

  • У Lua есть собственная поддержка сопрограмм.
    • ОБНОВЛЕНИЕ: JS теперь содержит ключевое слово yield внутри генераторов, предоставляя ему поддержку сопрограмм.
  • Lua не конвертирует между типами для любых операторов сравнения. В JS только === и !== не вводите жонглирование.
  • У Луа есть оператор возведения в степень (^); JS нет. В JS используются разные операторы, включая троичный условный оператор (?: Vs and/or) и, с версии 5.3, побитовые операторы (&, | и т.д. По сравнению с метаметодами).
    • ОБНОВЛЕНИЕ: JS теперь имеет оператор возведения в степень **.
  • JS имеет приращение/уменьшение, операторы типа (typeof и instanceof), дополнительные операторы присваивания и дополнительные операторы сравнения.
  • В JS операторы ==, === != И !== имеют меньший приоритет, чем >, >=, <, <=. В Lua все операторы сравнения имеют одинаковый приоритет.
  • Lua поддерживает хвостовые вызовы.
  • Lua поддерживает присвоение списку переменных. Хотя он еще не является стандартным в Javascript, движок Mozilla JS (и, в некоторой степени, Opera) поддерживает аналогичную функцию начиная с JS 1.7 (доступна как часть Firefox 2) под названием " назначение деструктурирования ". Разрушение в JS является более общим, поскольку оно может использоваться в контекстах, отличных от присваивания, таких как определения функций и вызовы и инициализаторы цикла. Деструктурирующее назначение было предложенным дополнением к ECMAScript (стандарт языка, стоящий за Javascript) на некоторое время.
    • ОБНОВЛЕНИЕ: Деструктурирование (и назначение деструктурирования) теперь является частью спецификации для ECMAScript - уже реализовано во многих движках.
  • В Lua вы можете перегружать операторов.
  • В Lua вы можете манипулировать средами с помощью getfenv и setfenv в Lua 5.1 или _ENV в Lua 5.2 и 5.3.
  • В JS все функции являются переменными. В Lua функции должны быть явно объявлены как variadic.
  • Foreach в JS зацикливает свойства объекта. Foreach в Lua (который использует ключевое слово for) зацикливается на итераторах и носит более общий характер.
    • ОБНОВЛЕНИЕ: У JS теперь есть Iterables, многие из которых встроены в обычные структуры данных, которые вы ожидаете, такие как Array. Они могут быть зациклены с помощью синтаксиса for...of Для обычных объектов можно реализовать свои собственные функции итератора. Это приближает его к Луа.
  • JS имеет глобальную и функциональную область применения. Lua имеет глобальную и блокированную область видимости. Управляющие структуры (например, if, for, while) вводят новые блоки.

    • Из-за различий в правилах области видимости, закрывающая ссылка на внешнюю переменную (называемую "upvalues" на языке Lua) может обрабатываться по-разному в Lua и в Javascript. Чаще всего это опыт работы с затворами for петель, и ловит некоторых людей врасплох. В Javascript тело цикла for не вводит новую область видимости, поэтому все функции, объявленные в теле цикла, ссылаются на одни и те же внешние переменные. В Lua каждая итерация цикла for создает новые локальные переменные для каждой переменной цикла.

      local i='foo'
      for i=1,10 do
        -- "i" here is not the local "i" declared above
        ...
      end
      print(i) -- prints 'foo'
      

      Приведенный выше код эквивалентен:

      local i='foo'
      do
        local _i=1
        while _i<10 do
          local i=_i
          ...
          _i=_i+1
        end
      end
      print(i)
      

      Как следствие, функции, определенные в отдельных итерациях, имеют разные значения повышений для каждой ссылочной переменной цикла. Смотрите также Николас Бола ответы на реализацию замыканий в Lua? и " Какова правильная семантика замыкания над переменной цикла? " и " Семантика общего для ".

      ОБНОВЛЕНИЕ: JS теперь имеет область видимости блока. Переменные, определенные с помощью let или const относятся к области видимости блока.

  • Целочисленные литералы в JS могут быть в восьмеричном виде.
  • JS имеет явную поддержку Unicode, а внутренние строки кодируются в UTF-16 (поэтому они представляют собой последовательности пар байтов). Различные встроенные функции JavaScript используют данные Unicode, такие как "pâté".toUpperCase() ("PÂTÉ"). В Lua 5.3 и более поздних версиях имеются escape-последовательности кодовых точек Unicode в строковых литералах (с тем же синтаксисом, что и в escape-последовательностях кодовых точек JavaScript), а также встроенная библиотека utf8, которая обеспечивает базовую поддержку кодировки UTF-8 (например, кодирования кода). указывает на UTF-8 и декодирует UTF-8 в кодовые точки, получает количество кодовых точек в строке и перебирает кодовые точки). Строки в Lua представляют собой последовательности отдельных байтов и могут содержать текст в любой кодировке или произвольные двоичные данные. Lua не имеет никаких встроенных функций, которые используют данные Unicode; поведение string.upper зависит от локали языка C.
  • В Lua вместо JS используются ключевые слова not, or and ! , || &&.
  • Lua использует ~= для "не равно", тогда как JS использует !==. Например, if foo ~= 20 then... end.
  • Lua 5.3 и выше используют ~ для двоичного побитового XOR, тогда как JS использует ^.
  • В Lua для индексации таблицы может использоваться любой тип значения (кроме nil и NaN). В JavaScript все нестроковые типы (кроме Symbol) преобразуются в строки перед использованием для индексации объекта. Например, после оценки следующего кода значение obj[1] будет "string one" в JavaScript, но "number one" в Lua: obj = {}; obj[1] = "number one"; obj["1"] = "string one"; obj = {}; obj[1] = "number one"; obj["1"] = "string one"; ,
  • В JS присваивания обрабатываются как выражения, а в Lua - нет. Таким образом, JS разрешает присваивания в условиях операторов if, while и do while, а Lua - в операторах if, while и repeat until операторов. Например, if (x = 'a') {} является допустимым JS, но if x = 'a' do end является недействительным Lua.
  • У Lua есть синтаксический сахар для объявления переменных функций блочной области, функций, являющихся полями, и методов (local function() end function t.fieldname() end function t:methodname() end). JS объявляет их знаком равенства (let funcname = function optionalFuncname() {}, objectname.fieldname = function() {}).

Ответ 2

Чтобы быть честным, было бы легче перечислить вещи, которые являются общими для Javascript и Lua, чем перечислять различия. Они оба являются динамически типизированными языками сценариев, но это касается как можно дальше. Они имеют совершенно другой синтаксис, разные исходные цели дизайна, различные режимы работы (Lua всегда компилируется в байт-код и запускается на Lua VM, Javascript меняется), список можно продолжать и продолжать.

Ответ 3

Несколько тонких различий, которые поймают вас хотя бы один раз:

  • Не равный пишется ~= в Lua. В JS это !=
  • Lua массивы основаны на 1 - их первый индекс равен 1, а не 0.
  • Lua требует двоеточия, а не период для вызова методов объекта. Вы пишете a:foo() вместо a.foo() & dagger;

& dagger; вы можете использовать период, если хотите, но должны явно передавать переменную self. a.foo(a) выглядит немного громоздким. Подробнее см. Программирование в Lua.

Ответ 4

Матрицы и объекты JavaScript ближе, чем вы думаете. Вы можете использовать нотацию массива, чтобы получить элементы любого из них, и вы можете добавлять нечисловые индексы в массивы. Отдельные элементы массива могут содержать что угодно, и массив может быть разреженным. Это почти идентичные кузены.

Ответ 5

Сверху моей головы

Lua...

  • поддерживает сопрограммы
  • не имеет ограничений на просто строку/число как ключ для таблицы. Все работает.
  • обработка ошибок несколько неуклюжая. Либо вы ничего не обрабатываете, либо используете метод pcall
  • Я думаю, что я читал кое-что о различиях в лексической сфере и что у Lua есть лучший.
  • Если я правильно помню, поддержка регулярных выражений в lua ограничена

Ответ 6

Мне понравился этот вопрос и ответы предоставлены. Дополнительные причины, по которым два языка кажутся более похожими на меня:

И назначать функции переменным, может строить функции "на лету", и определить замыкания.

Ответ 7

Тест показывает, что текущий Javascript также возвращает объекты или, по крайней мере, строки из логических выражений, таких как lua:

function nix(){
    alert(arguments[0]||"0");
} 
nix();

Ответ 8

Lua и JavaScript являются прототипами базовых языков.