美文网首页Lua前端开发程序员
【译】从 JS 学习 Lua

【译】从 JS 学习 Lua

作者: NARUTO_86 | 来源:发表于2016-10-21 20:02 被阅读1008次

    原文: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,但是对于这篇文章中讨论的一些内容也有些自己的看法和补充,回头也整理下吧。

    相关文章

      网友评论

        本文标题:【译】从 JS 学习 Lua

        本文链接:https://www.haomeiwen.com/subject/pvwxuttx.html