I simply love JavaScript. It's so elegant (imagine the quiet sound of lovestruck fanboy sighing in the background).
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
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?
Some more differences:
===
and !==
don't type juggle.^
); 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 ).
**
.typeof
and instanceof
), additional assignment operators and additional comparison operators.==
, ===
, !=
and !==
operators are of lower precedence than >
, >=
, <
, <=
. In Lua, all comparison operators are the same precedence.getfenv
and setfenv
in Lua 5.1 or _ENV
in Lua 5.2 and 5.3.Foreach
in JS loops over object properties. Foreach in Lua (which use the keyword for
) loops over iterators and is more general.
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.
"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.not
, or
, and
keywords are used in place of JS's !
, ||
, &&
.~=
for "not equal", whereas JS uses !==
. For example, if foo ~= 20 then ... end
.~
for binary bitwise XOR, whereas JS uses ^
.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";
.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.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 () {}
).