JavaScript 和 Lua 之间的细微差别 [关闭]
Posted
技术标签:
【中文标题】JavaScript 和 Lua 之间的细微差别 [关闭]【英文标题】:subtle differences between JavaScript and Lua [closed] 【发布时间】:2010-11-04 14:04:24 【问题描述】:我只是喜欢 javascript。它是如此优雅(想象一下背景中失恋的歌迷安静的叹息声)。
所以,最近我通过 löve2d 框架使用 Lua(很好!) - 我认为 Lua 也很棒。在我看来,这两种语言非常相似。
有明显的区别,比如
语法 问题域 库 类型(有点)但哪些是更微妙的?有没有什么 JavaScript 编码员会认为在 Lua 中工作的东西只是略有不同?对于使用一种语言的经验丰富的编码人员尝试另一种语言时,是否存在任何可能不明显的陷阱?
例如:在 Lua 中,数组和散列不是分开的(只有表)——在 JavaScript 中,它们是数值数组和散列对象。嗯,这是比较明显的区别之一。
但是在变量范围、不变性或类似方面有区别吗?
【问题讨论】:
对于像我这样正在寻找整体比较并意外来到这里的人来说,以下是一个很好的概述:phrogz.net/lua/LearningLua_FromJS.html 这是一个由三部分组成的系列,解释了您需要了解的所有差异:oreilly.com/learning/… 【参考方案1】:更多区别:
Lua 原生支持coroutines。 更新:JS 现在在生成器中包含 yield 关键字,从而支持协程。 Lua doesn't convert 在任何比较运算符的类型之间。在 JS 中,只有===
和 !==
不输入 juggle。
Lua 有一个求幂运算符 (^
); JS 没有。 JS 使用不同的运算符,包括三元条件运算符(?:
与 and/or
),以及从 5.3 开始的位运算符(&
、|
等与 @987654323 @)。
更新:JS 现在有求幂运算符**
。
JS 具有递增/递减、类型运算符(typeof
和 instanceof
)、附加赋值运算符和附加比较运算符。
在 JS 中,==
、===
、!=
和 !==
运算符的优先级低于 >
、>=
、<
、<=
.在 Lua 中,所有比较运算符都是 same precedence。
Lua 支持tail calls。
更新:JS 现在supports tail calls。
Lua 支持assignment to a list of variables。虽然它在 Javascript 中还不是标准的,但 Mozilla 的 JS 引擎(在一定程度上也是 Opera 的)从 JS 1.7(作为 Firefox 2 的一部分提供)开始支持类似的功能,名称为“@987654328 @"。 JS 中的解构更为通用,因为它可以在赋值以外的上下文中使用,例如function definitions & calls 和loop initializers。 Destructuring assignment 已被提议添加到 ECMAScript(Javascript 背后的语言标准)有一段时间了。
更新:解构(和解构赋值)现在是 ECMAScript 规范的一部分 - 已经在许多引擎中实现。
在Lua中,你可以overload operators。
在 Lua 中,您可以使用 Lua 5.1 中的 getfenv
and setfenv
或 Lua 5.2 和 5.3 中的 _ENV
来操作环境。
在 JS 中,所有函数都是可变参数。在 Lua 中,函数必须是 explicitly declared as variadic。
JS 中的Foreach
循环对象属性。 Lua 中的Foreach(使用关键字for
)循环遍历迭代器并且更通用。
更新:JS 现在也有Iterables,其中许多都内置在您期望的常规数据结构中,例如Array
。这些可以使用for...of
语法循环。对于常规对象,可以实现自己的迭代器函数。这使它更接近 Lua。
JS 具有全局和函数作用域。 Lua 有global and block scope。控制结构(例如if
、for
、while
)引入了新的blocks。
由于作用域规则的不同,闭包对外部变量的引用(在 Lua 用语中称为“upvalues”)在 Lua 和 Javascript 中的处理方式可能不同。 closures in for
loops 最常遇到这种情况,这让一些人感到意外。在 Javascript 中,for
循环的主体不会引入新的范围,因此在循环主体中声明的任何函数都引用same outer variables。在 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)
因此,在单独的迭代中定义的函数对于每个引用的循环变量都有不同的上值。另请参阅 Nicolas Bola 对Implementation of closures in Lua? 和“What are the correct semantics of a closure over a loop variable?”和“The Semantics of the Generic for”的回答。
更新:JS 现在有块作用域。使用let
或const
定义的变量尊重块范围。
"pâté".toUpperCase()
("PÂTÉ"
)。 Lua 5.3 及更高版本在字符串文字中具有 Unicode 代码点转义序列(与 JavaScript 代码点转义序列具有相同的语法)以及内置的 utf8
库,它为UTF-8 encoding(例如将码点编码为 UTF-8 并将 UTF-8 解码为码点,获取字符串中码点的数量,以及对码点进行迭代)。 Lua 中的字符串是单个字节的序列,可以包含任何编码的文本或任意二进制数据。 Lua 没有任何使用 Unicode 数据的内置函数; string.upper
的行为取决于 C 语言环境。
在 Lua 中,not
、or
、and
关键字用于代替 JS 的 !
、||
、@ 987654392@.
Lua 使用 ~=
表示“不相等”,而 JS 使用 !==
。例如,if foo ~= 20 then ... end
。
Lua 5.3 及更高版本使用~
进行二进制按位异或,而JS 使用^
。
在 Lua 中,任何类型的值(nil
和 NaN
除外)都可用于索引表。在 JavaScript 中,所有非字符串类型(符号除外)在用于索引对象之前都会转换为字符串。例如,在评估以下代码后,obj[1]
的值在 JavaScript 中将为 "string one"
,但在 Lua 中为 "number 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 ()
)声明这些。
【讨论】:
在 Lua 中,逻辑运算符(和、或)确实返回参数之一。可以使用任意数量的参数调用所有函数;但被调整到需要的数字(除非你使用...'extra args') @RCIX:参见 luaconf.h(在 Lua 5.2 中,还有 lparser.c 和 llimits.h)。 Lua 5.1 和 Lua 5.2 中的最大局部值/函数 = 200。在 Lua 5.1 中 Max upvalues/function = 60,在 Lua 5.2 中为 255(这个计数还包括函数内部创建的闭包“继承”的 upvalues)。 我认为你可以将基于 1 的数组添加到列表中,如果你不习惯它会很烦人。 Lua 中只有 nil 和 false 是虚假的 - 例如,0 在 Lua 中是真实的,但在 js 中不是。关于 Unicode 支持:Lua 5.3 增加了一些明确的 UTF-8 支持,而旧的 Lua 版本对保存在字符串中的 UTF-8 缓冲区很友好(例如,您可以在字符串搜索模式中使用 Unicode)。 Js 对 UTF-8 的支持并不完美,因为 V8 内部使用旧的 16 位表示,因此您的 unicode 字符串可能以(惊喜!)在好的 ol' UTF-8 中不需要的代理对结束(并且赢得了'不会发生在 Lua 中)。 我喜欢这个列表,但我看不出~=
是如何引起微妙 错误的。它可能会引发语法错误,但它们一点也不微妙。【参考方案2】:
一些细微的差别至少会让你发现一次:
不等于在 Lua 中拼写为~=
。在 JS 中是!=
Lua arrays are 1-based - 它们的第一个索引是 1 而不是 0。
Lua 需要冒号而不是句点来调用对象方法。你写 a:foo()
而不是 a.foo()
†
† 您可以根据需要使用句点,但必须明确传递 self
变量。 a.foo(a)
看起来有点麻烦。详情请见Programming in Lua。
【讨论】:
使用†
作为注释使a.foo()
看起来像死了xD【参考方案3】:
说实话,列出 Javascript 和 Lua 的共同点要比列出差异更容易。它们都是动态类型的脚本语言,但这只是你能做到的。它们有完全不同的语法、不同的原始设计目标、不同的操作模式(Lua 总是编译为字节码并在 Lua VM 上运行,Javascript 各不相同),这样的例子不胜枚举。
【讨论】:
绝对。非常不同的目标包括拥有干净的语言的高优先级。 Javascript 有很多历史包袱,Lua 不断摆脱任何不受欢迎的东西。 +1。我什至看不出它们有什么相似之处,除了它们都用于编写脚本(这太明显了)。 -1(如果可以的话)它们在语言设计方面非常相似。 Lua 只是具有更多的功能并且更小(也更快?)。我认为您将语言设计与实现选择混淆了。 是的,它们都是原型 OOP(即使没有明确说明使用关键字prototype
或命名对象对象,尽管这正是 lua 表是什么),具有一流的功能公民尽管不是传统意义上的功能(不变性、声明式开发等),
当然,存在语法差异,如果您从表面上看,您可能会得出不同语言的结论。 然而在拥有完全相同的主要数据类型(对象/表)以及实现类和继承的相同方式(很少其他语言共享的东西)使它们惊人地接近精神上。非平凡的 JS 程序的设计与 Lua 程序的设计几乎相同。【参考方案4】:
JavaScript 数组和对象比你想象的更接近。您可以使用数组表示法来获取其中任何一个的元素,并且可以向数组添加非数字索引。单个数组元素可以容纳任何东西,并且数组可以是稀疏的。他们几乎是同卵。
【讨论】:
可以有相同的堂兄弟吗? 它们是相同的数据结构,唯一的区别是类型描述符,因此您可以区分它们。 更准确的说法是:数组是具有“长度”成员特殊行为的对象。 @eegg:当然,Cathy and Patty。【参考方案5】:我喜欢这个问题和提供的答案。这两种语言在我看来比不相似的其他原因:
两者 将函数分配给变量, 可以即时构建功能, 并定义闭包。
【讨论】:
他们开始不同,但逐渐趋同。【参考方案6】:想不通
Lua ...
-
支持coroutines
没有限制仅将字符串/数字作为表的键。一切正常。
错误处理有些笨拙。要么不处理任何事情,要么使用pcall 方法
我想我读过一些关于词法范围差异的文章,并且 Lua 有更好的词法范围。
如果我没记错的话,lua 中的正则表达式支持是有限的
【讨论】:
Lua 确实有词法范围。 JavaScript 只有函数作用域。好吧,在 Mozilla 和 Rhino 中,你现在可以使用 'let' 而不是 'var' 并获得适当的词法范围;但它还不能移植。 Lua 的标准字符串库包含有限的模式匹配函数;但还有 LPEG(也是一个库),它提供了一个更强大的匹配系统,可轻松用于完整的语法。 我说 LUA 比 javascript 具有“更好”的词法范围,而不是它没有。 LPEG 是一个附加库,这意味着核心正则表达式支持仅限于我 字符串键和数字键之间有一些限制,在同一个表中使用两者会很快变得混乱,因为 # 返回表长度,而不是编号索引的数量,这将与任何字典条目(在枚举表索引之后索引 nil)【参考方案7】:Lua 和 JavaScript 都是原型基础语言。
【讨论】:
这是两种语言之间明显的相似之处,这和它们使用表/哈希作为主要数据类型。如果您要习惯性地开发 Javascript 程序,您将采用与在 Lua 中几乎相同的方法。你不会在任何其他语言中做同样的事情(除非它是一种基于原型继承和表的语言)。这是一个巨大的相似之处。其余的,关于次要语法的细节等等,相比之下就相当迂腐了。 重要的区别在于 Jaavscript 不支持协程,与 C 的耦合不是很紧密,并不适合作为嵌入式语言。 (有多少微控制器是用 Javascript 编程的?)Javascript 也更加混乱,有大量遗留问题和 WAT (destroyallsoftware.com/talks/wat) - 从 1:40 开始。 Lua 有一个非常斯巴达式的纪律。当然,Javascript 在浏览器中非常强大。【参考方案8】:测试表明当前的 Javascript 也返回对象,或者至少像 lua 一样返回来自逻辑表达式的字符串:
function nix()
alert(arguments[0]||"0");
nix();
【讨论】:
以上是关于JavaScript 和 Lua 之间的细微差别 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
了解收集 `flat_map` 与收集 rust 中的 `map` 之间的细微差别
如何使用 JavaScript 获取 HTML 页面的标题?