JavaScript和Lua之间的细微差别[关闭]


121

我只是喜欢JavaScript。它是如此的优雅(想象一下背景中迷恋的歌迷的安静声音)。

因此,最近我通过löve2d框架与Lua一起(很好!)-我认为Lua也很棒。从我的角度来看,这两种语言非常相似。

有明显的差异,例如

  • 句法
  • 问题域
  • 图书馆
  • 类型(一点)

但是哪些是更微妙的呢?在Lua中工作的JavaScript编码器是否理所当然会略有不同?对于尝试使用另一种语言的经验丰富的编码人员来说,是否存在任何可能看不到的陷阱?

例如:在Lua中,数组和哈希不是分开的(只有表)-在JavaScript中,它们是数字数组和散列对象。好吧,这是最明显的差异之一。

但是在可变范围,不变性或类似方面是否存在差异?


8
对于像我这样的人,他们正在寻求总体比较并偶然地来到这里,以下是一个不错的概述:phrogz.net/lua/LearningLua_FromJS.html
Tao

这是一个由三部分组成的系列文章,介绍了入门时需要了解的所有差异:oreilly.com/learning/…–
charAt

Answers:


189

更多区别:

  • Lua协程具有本地支持。
    • 更新:JS现在在生成器中包含yield关键字,从而支持协程。
  • Lua 不会在任何比较运算符的类型之间进行转换。在JS中,只能输入===!==请勿输入杂项。
  • Lua有一个幂运算符(^);JS没有。JS使用不同的运营商,包括三元条件操作符(?:VS and/or),并且,如5.3,位运算符(的&|等与元方法)。
    • 更新:JS现在具有幂运算符**
  • JS具有递增/递减,类型运算符(typeofinstanceof),附加赋值运算符和附加比较运算符。
  • JS=====!=!==运营商都低于优先级>>=<<=。在Lua中,所有比较运算符都具有相同的优先级
  • Lua支持尾叫
  • Lua支持分配给变量列表。Mozilla的JS引擎(某种程度上还是Opera的)在Javascript中还不是标准,但自JS 1.7(作为Firefox 2的一部分提供)以来,就以“ 解构分配 ” 的名称支持了类似的功能。JS中的解构更为通用,因为它可以在赋值以外的其他上下文中使用,例如函数定义和调用以及循环初始化器。一段时间以来,建议将解构分配添加到ECMAScript(Javascript背后的语言标准)中。
    • 更新:解构(和解构分配)现在是ECMAScript规范的一部分-已在许多引擎中实现。
  • Lua中,您可以重载运算符
  • Lua中,你可以操纵与环境getfenvsetfenv在Lua 5.1或_ENVLua中5.2 5.3
  • JS中,所有函数都是可变参数。在Lua中,功能必须是显式声明为可变参数
  • ForeachJS中遍历对象属性。的foreach Lua中(其中使用关键字for)遍历迭代器和更通用。
    • 更新:JS 现在也具有Iterables,其中许多内置于您期望的常规数据结构中,例如Array。这些可以使用for...of语法进行循环。对于常规对象,可以实现自己的迭代器功能。这使它更接近Lua。
  • JS具有全局和功能范围。Lua具有全局范围和块范围。控制结构(例如ifforwhile)引入新的

    • 由于作用域规则的差异,在Lua和Javascript中,对外部变量的闭包引用(在Lua措辞中称为“ upvalues”)可能会有所不同。这是循环闭包中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)

      结果,对于每个引用的循环变量,在单独的迭代中定义的函数具有不同的上限值。另请参阅Nicolas Bola 对在Lua中实施关闭的回答和“ 对循环变量进行闭包的正确语义是什么? ”和“泛型的语义 ”。

      更新:JS现在具有块作用域。与定义的变量letconst对于块范围。

  • 中的整数文字 JS中的可以是八进制的。
  • JS具有显式的Unicode支持,并且内部字符串以UTF-16编码(因此它们是字节对序列)。各种内置的JavaScript函数都使用Unicode数据,例如"pâté".toUpperCase()"PÂTÉ")。Lua 5.3及更高版本具有字符串文字中的Unicode代码点转义序列(与JavaScript代码点转义序列具有相同的语法)以及内置utf8库,该库提供对UTF-8编码的基本支持(例如,将代码点编码为UTF-8,将UTF-8解码为代码点,获取字符串中代码点的数量,以及遍历代码点)。Lua中的字符串是单个字节的序列,可以包含任何编码形式的文本或任意二进制数据。Lua没有使用Unicode数据的内置函数;的行为string.upper取决于C语言环境。
  • Lua中notorand关键字代替使用JS!||&&
  • 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";
  • JS中,赋值被视为表达式,而在Lua中则不被视为表达式。因此,JS允许分配的条件下ifwhiledo while语句,但是在Lua中没有ifwhilerepeat until语句。例如,if (x = 'a') {}有效的JS,但if x = 'a' do end无效的Lua。
  • LUA具有用于声明块范围的函数的变量,即是字段功能语法糖,和方法(local function() endfunction t.fieldname() endfunction t:methodname() end)。JS用等号(let funcname = function optionalFuncname() {}objectname.fieldname = function () {})声明它们。

6
在Lua中,逻辑运算符(和(或))确实返回参数之一。可以使用任意数量的参数调用所有函数;但已调整为所需的数字(除非您使用...'extra args')
Javier

1
@RCIX:请参见luaconf.h(在Lua 5.2中,另请参见lparser.c和llimits.h)。在Lua 5.1和Lua 5.2中,最大局部值/功能= 200。在Lua 5.1中,最大升值/函数= 60,在Lua 5.2中为255(此计数还包括在函数内部创建的闭包“继承”的升值)。
dubiousjim 2012年

8
我认为您可以将基于1的数组添加到列表中,当您不习惯它时可能会很烦。
Yann 2014年

2
在Lua中,只有nil和false是虚假的-因此,例如,在Lua中0是真实的,而在js中不是。关于Unicode支持:Lua 5.3添加了一些显式的UTF-8支持,并且较旧的Lua版本对字符串中包含的UTF-8缓冲区很友好(例如,您可以在字符串搜索模式中使用Unicode)。Js对UTF-8的支持不是完美的,因为V8内部使用了旧的16位表示形式,因此您的unicode字符串可能会以(surprrise!)替代对结尾,而这些替代对在良好的UTF-8中是不需要的(并赢得了在Lua不会发生)。
泰勒(Tyler)2015年

4
我喜欢这个列表,但是我看不到如何~=引发细微的错误。它可能会引发语法错误,但是它们并不是很细微。
kikito 2015年

12

有一些细微的差异,至少会吸引您一次:

  • ~=Lua中拼写不相等。在JS中!=
  • Lua 数组基于1-它们的第一个索引是1而不是0。
  • Lua需要冒号而不是句点来调用对象方法。您写a:foo()而不是a.foo()

如果需要,可以使用句点,但必须self显式传递变量。a.foo(a)看起来有点麻烦。有关详细信息,请参见在Lua中编程


5
使用注释使a.foo()xD 似乎已经死亡
DarkWiiPlayer

11

老实说,列出Javascript和Lua的共同之处要比列出差异要容易。它们都是动态类型的脚本语言,但这实际上是可以做到的。它们具有完全不同的语法,不同的原始设计目标,不同的操作模式(Lua始终会编译为字节码并在Lua VM上运行,Javascript会有所不同),列表不胜枚举。


8
绝对。非常不同的目标包括拥有清晰语言的高度优先权。Javascript有很多历史包g,Lua不断散布不想要的东西。
哈维尔2009年

3
+1。我什至看不到它们有什么相似之处,只是它们都用于脚本编制(这太明显了)。
Sasha Chedygov

13
-1(如果可以的话)在语言设计方面非常相似。Lua具有更多功能,却更小(还更快?)。我认为您将语言设计与实现选择混淆了。
jpc 2011年

是的,它们都是原型OOP(即使未使用关键字prototype或命名对象对象明确声明,尽管事实正是lua表是这样),尽管没有传统意义上的功能(不变性),但它们具有一等公民的功能。 ,声明性开发等),
Bojan Markovic

2
当然,在语法上存在差异,如果从表面上看它,您可能会得出结论,语言是不同的。然而在具有完全相同的主数据类型(对象/表),并实现类和inherritance(的东西,以同样的方式少数其他语言共享),使他们惊人的接近精神。非平凡的JS程序的设计与Lua的程序几乎相同。
亚历克斯·吉安

7

JavaScript数组和对象比您想象的要近。您可以使用数组表示法来获取它们中任意一个的元素,并且可以向数组添加非数字索引。单个数组元素可以容纳任何内容,并且数组可以是稀疏的。他们几乎是表亲。


1
可以有相同的表亲吗?
jameshfisher 2011年

它们是相同的数据结构,唯一的区别是类型描述符,因此您可以区分它们。
莉莉丝·里弗

5
一个更准确的说法是:数组是具有“长度”成员特殊行为的对象。
tzenes 2011年

@eegg:好的,Cathy和Patty
2012年

3

从我的头顶

a ...

  1. 支持协程
  2. 没有限制只将字符串/数字作为表的键。一切正常。
  3. 错误处理有些笨拙。您什么都不处理或使用pcall方法
  4. 我想我读到一些有关词汇范围差异的知识,而Lua则更好。
  5. 如果我没记错的话,lua中对正则表达式的支持是有限的

Lua 确实有词汇范围。JavaScript仅具有功能范围。好吧,在Mozilla和Rhino中,您现在可以使用'let'代替'var'并获得适当的词汇范围;但是还不能移植。
哈维尔2009年

1
Lua的标准字符串库包括有限的模式匹配功能。但是还有LPEG(也是一个库),它提供了更强大的匹配系统,可轻松用于完整的语法。
哈维尔2009年

我说过LUA具有“更好的”词法范围,而javascript则没有。
抖动

1
LPEG是一个附加库,这意味着核心正则表达式支持仅限于我
抖动

字符串键和数字键之间有些限制,在同一个表中使用它们会很快变得混乱,因为#返回表的长度,而不是编号索引的数量,这将与任何字典条目冲突(枚举后索引为nil表索引)
Weeve Ferrelaine 2014年

3

我喜欢这个问题和提供的答案。这两种语言在我看来似乎更像的其他原因:

两者都将函数分配给变量,可以即时构建函数,并定义闭包。


1

Lua和JavaScript都是原型基本语言。


1
这是两种语言之间的明显相似之处,这与表/哈希作为主要数据类型的使用有关。如果要惯用地开发Javascript程序,则采用与Lua中几乎相同的方法。您不会用其他任何语言做同样的事情(除非它是基于原型继承和表的语言)。这是一个巨大的相似之处。其余的,关于次要语法的细节等等,相比之下,都是相当古板的。
亚历克斯·吉安

1
重要的区别是Jaavscript不支持协程,与C结合得不是很紧密,也不适合用作嵌入式语言。(有多少微控制器的Javascript编程?)投票也更混乱,与传统吨和陷阱WATS(的destroyallsoftware.com/talks/wat) - 1:40。Lua被强加了斯巴达式的纪律。当然,JavaScript在浏览器中非常强大。
亚历克斯·吉安

1

测试表明,当前的Javascript也返回对象,或者至少从逻辑表达式中返回字符串,例如lua:

function nix(){
    alert(arguments[0]||"0");
} 
nix();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.