subtle differences between JavaScript and Lua
JavascriptLuaJavascript Problem Overview
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?
Javascript Solutions
Solution 1 - Javascript
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 (?:
vsand/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
andinstanceof
), 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.
- UPDATE: JS now 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
andsetfenv
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 keywordfor
) 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 thefor...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 afor
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 thefor
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
orconst
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-inutf8
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 ofstring.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
andNaN
) 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 ofobj[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
, anddo while
statements, but Lua does not inif
,while
, andrepeat until
statements. For example,if (x = 'a') {}
is valid JS, butif 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 () {}
).
Solution 2 - Javascript
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 ofa.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.
Solution 3 - Javascript
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.
Solution 4 - Javascript
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.
Solution 5 - Javascript
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.
Solution 6 - Javascript
Off the top of my head
Lua ...
- supports coroutines
- has no restriction to just string/number as key for a table. Everything works.
- the error handling is somewhat clumsy. Either you don't handle anything or use the pcall method
- I think I read something about differences in the lexical scope and that Lua has the better one.
- If I recall correctly regular expression support in lua is limited
Solution 7 - Javascript
Lua and JavaScript are both prototype base languages.
Solution 8 - Javascript
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();