124

I simply love JavaScript. It's so elegant.

So, recently I have played with Lua via the löve2d framework (nice!) - and I think Lua is also great. They way I see it, those two languages are very similar.

There are obvious differences, like

  • syntax
  • problem domain
  • libraries
  • types (a bit)

but which are the more subtle ones? Is there anything a JavaScript coder would take for granted that works in Lua just slightly different? Are there any pitfalls that may not be obvious to the experienced coder of one language trying the other one?

For example: in Lua, arrays and hashes are not separate (there are only tables) - in JavaScript, they are numerical Arrays and hashed Objects. Well, this is one of the more obvious differences.

But are there differences in variable scope, immutability or something like this?

stefs
  • 18,341
  • 6
  • 40
  • 47
  • 10
    For those, like me, who were looking for an overall comparison and ended up here by accident, the following is a nice overview: http://phrogz.net/lua/LearningLua_FromJS.html – Tao May 02 '12 at 10:55
  • This is a three part series explaining all the differences you'll need to know to get started: https://www.oreilly.com/learning/learn-lua-from-javascript-part-1-an-introduction-to-lua – charAt Feb 02 '19 at 06:36

8 Answers8

200

Some more differences:

  • Lua has native support for coroutines.
    • UPDATE: JS now contains the yield keyword inside generators, giving it support for coroutines.
  • Lua doesn't convert between types for any comparison operators. In JS, only === and !== don't type juggle.
  • Lua has an exponentiation operator (^); JS doesn't. JS uses different operators, including the ternary conditional operator (?: vs and/or), and, as of 5.3, bitwise operators (&, |, etc. vs. metamethods ).
    • UPDATE: JS now has the exponentiation operator **.
  • JS has increment/decrement, type operators (typeof and instanceof), additional assignment operators and additional comparison operators.
  • In JS, the ==, ===, != and !== operators are of lower precedence than >, >=, <, <=. In Lua, all comparison operators are the same precedence.
  • Lua supports tail calls.
  • Lua supports assignment to a list of variables. While it isn't yet standard in Javascript, Mozilla's JS engine (and Opera's, to an extent) has supported a similar feature since JS 1.7 (available as part of Firefox 2) under the name "destructuring assignment". Destructuring in JS is more general, as it can be used in contexts other than assignment, such as function definitions & calls and loop initializers. Destructuring assignment has been a proposed addition to ECMAScript (the language standard behind Javascript) for awhile.
    • UPDATE: Destructuring (and destructuring assignment) is now part of the spec for ECMAScript - already implemented in many engines.
  • In Lua, you can overload operators.
  • In Lua, you can manipulate environments with getfenv and setfenv in Lua 5.1 or _ENV in Lua 5.2 and 5.3.
  • In JS, all functions are variadic. In Lua, functions must be explicitly declared as variadic.
  • Foreach in JS loops over object properties. Foreach in Lua (which use the keyword for) loops over iterators and is more general.
    • UPDATE: JS has Iterables now too, many of which are built into the regular data structures you'd expect, such as Array. These can be looped over with the for...of syntax. For regular Objects, one can implement their own iterator functions. This brings it much closer to Lua.
  • JS has global and function scope. Lua has global and block scope. Control structures (e.g. if, for, while) introduce new blocks.

    • Due to differences in scoping rules, a closure's referencing of an outer variable (called "upvalues" in Lua parlance) may be handled differently in Lua and in Javascript. This is most commonly experienced with closures in for loops, and catches some people by surprise. In Javascript, the body of a for loop doesn't introduce a new scope, so any functions declared in the loop body all reference the same outer variables. In Lua, each iteration of the for loop creates new local variables for each loop variable.

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

      The above code is equivalent to:

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

      As a consequence, functions defined in separate iterations have different upvalues for each referenced loop variable. See also Nicolas Bola's answers to Implementation of closures in Lua? and "What are the correct semantics of a closure over a loop variable?", and "The Semantics of the Generic for".

      UPDATE: JS has block scope now. Variables defined with let or const respect block scope.

  • Integer literals in JS can be in octal.
  • JS has explicit Unicode support, and internally strings are encoded in UTF-16 (so they are sequences of pairs of bytes). Various built-in JavaScript functions use Unicode data, such as "pâté".toUpperCase() ("PÂTÉ"). Lua 5.3 and up have Unicode code point escape sequences in string literals (with the same syntax as JavaScript code point escape sequences) as well as the built-in utf8 library, which provides basic support for the UTF-8 encoding (such as encoding code points into UTF-8 and decoding UTF-8 into code points, getting the number of code points in a string, and iterating over code points). Strings in Lua are sequences of individual bytes and can contain text in any encoding or arbitrary binary data. Lua does not have any built-in functions that use Unicode data; the behavior of string.upper depends on the C locale.
  • In Lua, the not, or, and keywords are used in place of JS's !, ||, &&.
  • Lua uses ~= for "not equal", whereas JS uses !==. For example, if foo ~= 20 then ... end.
  • Lua 5.3 and up use ~ for binary bitwise XOR, whereas JS uses ^.
  • In Lua, any type of value (except nil and NaN) can be used to index a table. In JavaScript, all non-string types (except Symbol) are converted to strings before being used to index an object. For example, after evaluation of the following code, the value of obj[1] will be "string one" in JavaScript, but "number one" in Lua: obj = {}; obj[1] = "number one"; obj["1"] = "string one";.
  • In JS, assignments are treated as expressions, but in Lua they are not. Thus, JS allows assignments in conditions of if, while, and do while statements, but Lua does not in if, while, and repeat until statements. For example, if (x = 'a') {} is valid JS, but if x = 'a' do end is invalid Lua.
  • Lua has syntactic sugar for declaring block-scoped function variables, functions that are fields, and methods (local function() end, function t.fieldname() end, function t:methodname() end). JS declares these with an equals sign (let funcname = function optionalFuncname() {}, objectname.fieldname = function () {}).
cyclaminist
  • 1,697
  • 1
  • 6
  • 12
outis
  • 75,655
  • 22
  • 151
  • 221
  • 6
    in Lua, logical operators (and, or) do return one of the arguments. all functions can be called with any number of parameters; but are adjusted to the needed number (unless you use the ... 'extra args') – Javier Jun 20 '09 at 23:05
  • thanks, that's a very nice list (and exactly what i hoped for). "# In Lua, logical operators return boolean values. In JS logical operators return the value of one of their arguments." you switched those, as javier noticed. – stefs Jun 21 '09 at 01:03
  • Whoops. Corrected false statement about logical operators. The statement about ! in Lua threw me. That'll teach me to read too fast. Community wiki, so keep adding everyone. – outis Jun 21 '09 at 01:53
  • A default Lua installation has limitations (usually 250-256) on numbers of locals/globals that can be declared in a program. – SztupY Jun 21 '09 at 01:57
  • Since when? i don't recall that... Perhaps a memory limitation on whatever you were testing on? – RCIX Sep 07 '09 at 14:14
  • Only relevant limits are 200 values on stack (those include locals, arguments, "for" internal state variables and temporary place for called functions arguments and returns) and 60 upvalues per function (not per block!). There's also limit on number of distinct constant, but you shouldn't hit unless you operate on high amount of non-uniform data. – Oleg V. Volkov Apr 23 '12 at 09:53
  • 1
    @RCIX: see luaconf.h (and in Lua 5.2, also lparser.c and llimits.h). Max local values/function = 200 in Lua 5.1 and Lua 5.2. Max upvalues/function = 60 in Lua 5.1, 255 in Lua 5.2 (and this count includes also upvalues "inherited by" closures created inside the function). – dubiousjim Jun 01 '12 at 18:54
  • Minor points, but `nil` isn't a valid lua table index, and lua's "foreach" is strictly the generic 'for'; `for p1[...,pn] in iter()`. – Textmode Aug 26 '13 at 04:19
  • @Textmode: When I wrote "foreach", I was referring to the semantics rather than the syntax; answer updated to clarify. Thanks for the note about `nil`; updated answer to include. – outis Aug 27 '13 at 20:28
  • You should note that ternary operators in Lua and pseudo, but actually quite nice. When Lua evaluates a Boolean statement, the last argument is returned. `return something and 35 or 1` will return 35 if something is `true`, and `1` if something is false. – Stormswept Apr 23 '14 at 14:10
  • 8
    I think you can add 1-based arrays to the list, it can be pretty annoying when you are not used to it. – Yann Aug 05 '14 at 13:03
  • 2
    Only nil and false are falsy in Lua - so, for example, 0 is truthy in Lua but not in js. About Unicode support: Lua 5.3 adds some explicit UTF-8 support, and older Lua versions are friendly to UTF-8 buffers held in strings (eg you can use Unicode in string search patterns). Js support of UTF-8 is not perfect as V8 internally uses an old 16-bit representation, so your unicode strings may end up with (surprise!) surrogate pairs that wouldn't be needed in good ol' UTF-8 (and won't happen in Lua). – Tyler Jan 07 '15 at 19:05
  • 5
    I loved this list, but I don't see how `~=` can provoke *subtle* bugs. It can provoke *syntax errors*, but they are not at all subtle. – kikito Jan 25 '15 at 20:27
  • Great post! Thank you. One thing though: JavaScript does have a more general `for` loop too that uses the `for` keyword, and is capable of being an optimized iterator. It's only used to iterate over object properties if you use the `in` keyword (e.g. `for key in object`). And neither of these uses are the same as JavaScript's `forEach`, which iterates over elements in an array (e.g. `[el1, el2, el3].forEach(handler)`). Seems worth mentioning too because the `forEach` method is native to JS arrays, and thus provides block-like scope (via the function handler) when iterating this way. – Benny Schmidt Aug 05 '15 at 22:29
  • Lua [supports](http://www.lua.org/manual/5.3/manual.html#3.4.2) bitwise operators now. There are no typeof and instanceof operators, but OOP libraries usually provide functions for that. – spbnick Aug 25 '15 at 16:01
  • Lua actually does have a type() function, and while I'm not too experienced with Javascript, it looks to works similar of not the same as JS's typeof(). – Accumulator Jan 12 '16 at 19:01
  • So how come, at the time, there was a need to create javascript instead of just using lua? – Dragas Nov 18 '18 at 07:09
  • @Dragas: comments aren't intended to address additional questions, so let's shift this to [chat](https://chat.stackoverflow.com/rooms/183916/why-create-javascript-instead-of-just-using-lua). – outis Nov 20 '18 at 03:23
  • Lua has goto :-p – Hibou57 May 08 '20 at 14:52
14

A couple of subtle differences that will catch you out at least once:

  • Not equal is spelled ~= in Lua. In JS it is !=
  • Lua arrays are 1-based - their first index is 1 rather than 0.
  • Lua requires a colon rather than a period to call object methods. You write a:foo() instead of a.foo()

you can use a period if you want, but have to pass the self variable explicitly. a.foo(a) looks a bit cumbersome. See Programming in Lua for details.

richq
  • 55,548
  • 20
  • 150
  • 144
12

To be honest it would be easier to list the things which are common to Javascript and Lua than to list the differences. They are both dynamically-typed scripting languages, but that's about as far as you can go really. They have totally different syntax, different original design goals, different modes of operation (Lua is always compiled to bytecode and run on the Lua VM, Javascript varies), the list goes on and on.

DaveR
  • 9,540
  • 3
  • 39
  • 58
  • 8
    absolutely. the very different goals include a high priority for having a clean language. Javascript has a lot of historical baggage, Lua continually sheds anything that's undesired. – Javier Jun 20 '09 at 23:07
  • 3
    +1. I don't even see how they're similar at all, except for the fact that they're both used for scripting (which is too obvious). – Sasha Chedygov Jun 21 '09 at 01:59
  • 15
    -1 (if I could) They are very similar on the language design front. Lua simply has more features and is smaller (also faster?). I think you confuse language design with implementation choices. – jpc Apr 21 '11 at 10:36
  • 1
    Yeah, they are both prototype OOP (even if it's not explicitly stated using keyword `prototype` or naming objects objects, despite the fact that that's exactly what lua tables are), with functions as first-class citizen despite not being functional in the traditional sense (immutablility, declarative development etc.), – Bojan Markovic Jan 13 '16 at 13:44
  • 5
    Sure, there are syntactic differences and if you look at it superficially, you may conclude the languages are different. **However** in having exactly the same main data type (object/table) and the same way of implementing classes and inherritance (something that *very* few other languages share) makes them amazingly close in spirit. The design of non-trivial JS program would be pretty much the same as that of a Lua one. – Alex Gian Feb 10 '17 at 07:23
8

JavaScript arrays and objects are closer than you might think. You can use array notation to get at the elements of either of them, and you can add non-numeric indices to arrays. Individual array elements can hold anything, and the array can be sparse. They are nearly identical cousins.

Nosredna
  • 83,000
  • 15
  • 95
  • 122
4

I liked this question and the answers provided. Additional reasons the two languages seem more alike than not to me:

Both assign functions to variables, can build functions on the fly, and define closures.

WeakPointer
  • 3,087
  • 27
  • 22
3

Off the top of my head

Lua ...

  1. supports coroutines
  2. has no restriction to just string/number as key for a table. Everything works.
  3. the error handling is somewhat clumsy. Either you don't handle anything or use the pcall method
  4. I think I read something about differences in the lexical scope and that Lua has the better one.
  5. If I recall correctly regular expression support in lua is limited
jitter
  • 53,475
  • 11
  • 111
  • 124
  • Lua _does_ have lexical scope. JavaScript only has function scope. well, in Mozilla and Rhino yo can now use 'let' instead of 'var' and get proper lexical scope; but it's not portable yet. – Javier Jun 20 '09 at 23:08
  • 1
    Lua's standard string library includes limited pattern matching functions; but there's also LPEG (also a library), which gives a much more powerful matching system, easily usable for a full grammar. – Javier Jun 20 '09 at 23:10
  • I stated that LUA has the "better" lexical scope then javascript not that it hasn't any. – jitter Jun 20 '09 at 23:50
  • 1
    LPEG is an additional library which means core regex support is limited to me – jitter Jun 20 '09 at 23:51
  • there is somewhat of a restriction between string keys and number keys, using both in the same table gets messy very fast, as # returns table length, not by the amount of numbered indexes, which will conflict with any dictionary entry (indexing nil after enumerated table indexes) – Weeve Ferrelaine Jan 01 '14 at 19:37
2

Lua and JavaScript are both prototype base languages.

  • 1
    This is the obvious similarity between the two languages, this and their use of tables/hashes as the main data type. If you were to develop a Javascript program idiomatically, you would take pretty much the same approach as you would in Lua. You would not do the same in a ny other language (unless it's a language based on protype inherittance and tables). This is a huge similarity. The rest, details about minor syntax and so on are pretty pedantic in comparison. – Alex Gian Jan 07 '17 at 01:15
  • 1
    The important differences are that Jaavscript does not support coroutines, is not very tightly coupled with C, and is not really suitable as an embedded language. (How many microcontrollers are programmed in Javascript?) Javascript is also much messier, with tons of legacy gotchas and WATs (https://www.destroyallsoftware.com/talks/wat) - from 1:40. Lua has had a pretty Spartan discipline imposed. Javascript, of course, is very strong in the browser. – Alex Gian Jan 07 '17 at 01:30
1

A test reveals that current Javascript also returns objects, or at least strings from logic expressions like lua does:

function nix(){
    alert(arguments[0]||"0");
} 
nix();
Adder
  • 5,708
  • 1
  • 28
  • 56