【译】从 JS 学习 Lua

原文:Learning Lua/From JS


从 JS 学习 Lua

对 JavaScript 已经了解,想学习下 Lua?下面我们来快速列举下两者的相似和不同之处。更多资料见“学习 Lua”。

相似之处

区分大小写

Lua 和 JS 都区分大小写。truefalse 是布尔型字面量值,和 TrueTRUE 完全不同。

函数可以有可变数目的参数

在 Lua 中,和 JS 类似,可以向你的函数传递比声明的更多或更少的参数:

function showem( a, b, c )
  print( a, b, c )
end

showem( 'first' )                              --> first nil nil
showem( 'first', 'second' )                    --> first second nil
showem( 'first', 'second', 'third' )           --> first second third
showem( 'first', 'second', 'third', 'fourth' ) --> first second third 

JS 中通过特殊的 arguments 可以获取所有的实参。在 Lua 5.0 中,对应是称为 arg 的表,但是只收集通过特殊的 ... 在形参列表标记的那些形参:

function showem( a, b, ... )
  local output = tostring(a) .. "\t" .. tostring(b)
  for i,v in ipairs(arg) do
    output = output .. "\t#" .. i .. ":" .. v
  end
  print( output )
end

showem( 'first'  )                             --> first  nil
showem( 'first', 'second' )                    --> first  second
showem( 'first', 'second', 'third' )           --> first  second  #1:third
showem( 'first', 'second', 'third', 'fourth' ) --> first  second  #1:third  #2:fourth

在 Lua 5.1 中,表 arg 被“可变参数表达式(vararg expressions)”替代:

function showem( a, b, ... )
  local output = tostring(a) .. "\t" .. tostring(b)
  local theArgs = { ... }
  for i,v in ipairs( theArgs ) do
    output = output .. "\t#" .. i .. ":" .. v
  end
  print( output )
end

showem( 'first'  )                             --> first  nil
showem( 'first', 'second' )                    --> first  second
showem( 'first', 'second', 'third' )           --> first  second  #1:third
showem( 'first', 'second', 'third', 'fourth' ) --> first  second  #1:third  #2:fourth

哈希表(hash)通过中括号或点记法引用

在 JS 和 Lua 中,访问哈希表的索引可以通过中括号:

theage = gavin[ 'age' ]

或点记法:

theage = gavin.age

数值就是数值

在 JS 和 Lua 中,整数和浮点数没有区别,不同长度的对象也没有对应不同的类型。所有的数值在 Lua 中都是“数值(number)”。

语句以分号结尾

在 JS 和 Lua 中,分号(;)用于表明语句的结束。并且两门语言中在一行结尾的分号都是可选的。

在 JS 中,习惯上使用分号。在 Lua 中,习惯上不用分号。

缺省的全局变量

在 JS 中,如果在一个函数中为之前未出现的变量赋值,如果存在 var 关键字那么变量是局部变量,否则是全局变量:

function foo( )
{
  var jim = "This variable is local to the foo function";
  jam = "This variable is in global scope";
}

Lua 中也类似,关键字 local 声明局部变量,没有时则为全局变量:

function foo( )
  local jim = "This variable is local to the foo function";
  jam = "This variable is in global scope";
end

字符串以双引号和单引号为界

在 JS 和 Lua 中,字符串字面量允许使用单引号或双引号(成对)。和 JS 一样(但与 Ruby 或 PHP 不同),使用哪个没有区别。和 JS 一样,可以通过反斜杠在字符串中转义引号:

local moniker = 'Gavin \'Wiki\' Kistner'; --> Gavin 'Wiki' Kistner
local moniker = "Gavin 'Wiki' Kistner";   --> Gavin 'Wiki' Kistner
local moniker = 'Gavin "Wiki" Kistner';   --> Gavin "Wiki" Kistner
local moniker = "Gavin \"Wiki\" Kistner"; --> Gavin "Wiki" Kistner

头等函数

在 JS 和 Lua 中,函数是头等对象。这意味着可以将函数赋值给变量,作为参数传递,以及通过 () 进行调用:

mytable = { }
mytable.squareit = function( x )
  return x * x
end

thefunc = mytable.squareit
print( thefunc( 7 ) ) --> 49

函数是闭包

在 JS 和 Lua 中,函数对象是闭包(closure)。简单来说,这意味着函数可以访问其声明的位置所在的作用域中的局部变量,甚至在该作用域“消失”之后。

function MakeAdder( inBaseValue )
  return function( inValueToAdd )
    return inBaseValue + inValueToAdd
  end
end

add10 = MakeAdder( 10 )
add30 = MakeAdder( 30 )
print( add10( 1 ) )  --> 11
print( add10( 6 ) )  --> 16
print( add30( 3 ) )  --> 33

不同之处

单行和多行注释

在 JS 中,单行注释以 // 开始。

在 Lua 中,注释以 -- 开始。

在 JS 中,多行注释使用 /* ... */ 来包裹内容。第一个出现的 */ 结束注释。

在 Lua 中,多行注释像这样 --[[ ... ]]。在 5.0 中,可以在注释中使用嵌套的 [[ ... ]]。在 5.1 中,多行注释可以有任意多个成对出现的等号(包括0个),如 --[==[ ... ]===]

Lua 多行注释的神奇之处在于,可以通过增加单个字符实现启用或禁用整个多行注释块:

-- This is a single line Lua comment
local jim = "This is not commented"
--[[
local foo = "This code is not active"
local bar = "Neither is this code line"
--]]

local jam = "This line is active"
---[[
local foo = "This code is ALSO active"
local bar = "because of the extra hyphen above"
--]]

使用 end 而非大括号

Lua(类似 Ruby)使用关键字 end 来关闭代码块。例如:

function foo( )
  --my code here
end

if foo( ) then
  --my code here
end

for i=0,1000 do
  --my code here
end

null 是 nil

在 Lua 中,“空”值以关键字 nil 表示,而非 JS 的 null

nil 和 false 是仅有的非真的值

在 JavaScript 中,""0 在条件判断时都等于 false。在 Lua 中,只有 nilfalse 等于 false

任何值都可以是表的索引

在 JavaScript 中,作为对象的索引的值始终是字符串。(在 JS 中,myObj[11] 与myObj["11"] 相同。)在 Lua 中,字符串,数值,甚至表都可以是索引:

a = {}
b = {}
mytable = {}
mytable[1] = "The number one"
mytable["1"] = "The string one"
mytable[a] = "The empty table 'a'"
mytable[b] = "The empty table 'b'"

print( mytable["1"] ) --> The string one
print( mytable[1] )   --> The number one
print( mytable[b] )   --> The empty table 'b'
print( mytable[a] )   --> The empty table 'a'

没有数组

在 JS 中,有明确的数组类型。它是一个基本的对象(哈希),在设置像整数的值时会修改 length 属性,同时也定义有特殊的方法:

var myArray = new Array( 10 );
var myOtherArray = [ 1, 2, 3 ];

在 Lua 中,表(table)是对象(object),表是原型(prototype),表是哈希(hash),表是数组(array),表...

Lua 中的“数组”是表,只不过有整数属性,且从 1(不是0!)开始连续编号,直到遇到第一个 nil 值。可以通过表字面量来创建数组,这样不必为每个值标出索引:

people = { "Gavin", "Stephen", "Harold" }
-- the above is the exact same as:
people = { [1]="Gavin", [2]="Stephen", [3]="Harold" }

table 有两个方法直接操作作为数组使用的表的“长度”,从而可以初始化一个元素为 nil 的“数组”:

people = { "Gavin", "Stephen", "Harold" }
print( table.getn( people ) )              --> 3

people[ 10 ] = "Some Dude"
print( table.getn( people ) )              --> 3
print( people[ 10 ] )                      --> "Some Dude"
for i=1,table.getn( people ) do
  print( people[ i ] )
end
--> Gavin
--> Stephen
--> Harold

table.setn( people, 10 )
print( table.getn( people ) )              --> 10

for i=1,table.getn( people ) do
  print( people[ i ] )
end
--> Gavin
--> Stephen
--> Harold
--> nil
--> nil
--> nil
--> nil
--> nil
--> Some Dude

数值、字符串和表是非 OOP 对象

在 Lua 中,过程式编程是王道。没有 myString.length 属性,也没有 myString.toLowerCase() 方法。只能使用库函数:

mystring = "Hello World"
print( string.len( mystring ) )    --> 11
print( string.lower( mystring ) )  --> hello world

这在 5.1 有所变更

没有 ++,没有 --

对不起,Lua 中没有简写的方法,只能用啰嗦的写法。

local themessage = "Hello"
themessage = themessage .. " World"

local thecounter = 1
thecounter = thecounter + 1

没有三元运算符

方便的 a ? b : c 语法在 Lua 中没有提供。不过,使用 andor 能够(大多数情况下)满足需要:

local foo = ( math.random( ) > 0.5 ) and "It's big!" or "It's small!"

local numusers = 1
print( numusers .. " user" .. ( numusers == 1 and " is" or "s are" ) .. " online." )
--> 1 user is online.

numusers = 10
print( numusers .. " user" .. ( numusers == 1 and " is" or "s are" ) .. " online." )
--> 10 users are online.

注意,这并不能直接替代三元表达式的使用情况。JavaScript 代码 m = x ? y : z始终xtrue(或为“真”)时将 y 赋值给 m

而 Lua 代码 m = x and y or z 会在 xtrue并且 y 也不是 falsenil 时将 y 赋值给 m

local x=true, y=false, z="oops"
if x then
  print( y )
else
  print( z )
end
--> false

print( x and y or z )
--> "oops"

尽管你可能很少注意到,上面的例子在 JavaScript 中也可以通过 &&|| 实现。而且在 JS 中甚至更危险,因为有更多的“非真”的值,例如空字符串 ""

// 下面的 JavaScript 代码无法正常工作,它会始终输出一个 's'。
var cats = 1;
console.log( "I have " + cats + " cat" + (cats==1 && "" || "s") + "." );
"I have 1 cats."

其他方面

我(译注:作者)太懒了,不想再写更多内容,就列下其他的东西吧:


虽然我也是刚接触 Lua,但是对于这篇文章中讨论的一些内容也有些自己的看法和补充,回头也整理下吧。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容