JavaScriptとLuaを比べてみた

ChainZ(クリエイター)
いろいろやってます。

最近ゲームを作る時に、Luaを使ってプロトタイプを作成しています。Luaはゲーム業界でよく知られている言語で、ゲーム中のイベントやAIなどのロジカルはLuaで組むことが多いです

一ヶ月近くLua使ってみたら、JavaScriptとかなり似ている部分があるなと思いました。JavaScriptとLuaともEvent Drivenに適切な言語で、プロトタイプを作るには結構便利で効率がいいです。

この二つの言語正直あまり関係ないですが、自分はJavaScriptをよく使っているので、Luaを書いてる時になんとなくJavaScriptと比較したくなります。

変数

JavaScriptでは変数の宣言はvarを使いますが、Luaではlocalを使います。

LuaとJavaScriptは変数のがなくて、言語自身がそれを面倒を見てもらいます。Luaではlocalを使わずに変数を宣言すると、グロバール変数になってしまいます。ブラウザバージョンのJavaScriptも同じ挙動です。

JavaScriptとLua両方ともできるだけグロバール変数を使わないように。特にLuaではグロバール変数にアクセスするのはパフォーマンスコストが高いです。

function

LuaとJavaScriptともfunctionがあります。一番大きいな違いは、JavaScriptのfunctionの優先順位は一番高いが、Luaはそうではないです。例で説明すると:

JavaScript

1
2
3
4
Hello(); // Helloの定義は次に来るが、問題なくコールされます。
function Hello() {
    console.log('Hello World');
}

Lua

1
2
3
4
Hello() // 上記のJavaScriptと同じく、Helloの定義が次に来るが、エラーです。
local function Hello()
    print('Hello World')
end

もちろん、LuaとJavaScriptとの文法も若干違います。あとで説明します。

JavaScriptのfunctionはスクリプトが実行される前に、定義の順番と関係なく、一番最初に解析されます。Luaは定義の順番に実行されます。

文法の違い

Luaの文法は若干くせがついています。もちろん慣れたらいいんですが、未だに自分はLuaのend文法に慣れていないです。

if文

JavaScriptはCスタイルの文法を使っています。

1
2
3
4
5
6
var ok = true;
if (ok) {
    console.log('OK');
} else {
    console.log('Ops');
}

Luaの場合:

1
2
3
4
5
6
local ok = true
if ok then
   print('OK')
else
   print('Ops')
end

Luaでは;をあまり使わないです。JavaScriptも;を使わなくて特に問題ないですが、コーディング習慣としてはよくないので、個人的にはあまりおすすめしません。

Luaのthenendは本当に書き忘れがちです。

演算子

Luaでは!=を使わず、~=と書きます。これ間違えやすいです。Luaでは否の演算子が!ではなくnotです。これは他の言語と比べたら結構癖が強いです。あと||&&orandになります。英語圏の人間にとっては読みやすいかもしれないですが、他の言語から来た人間は慣れるには少し時間かかりますね。

そして、他の言語でよくある+++=もLuaでは使えないです。素直にi = i + 1を書くしかないです。

JavaScriptはJSONのフォーマットでオブジェクトが作成できます:

1
2
3
4
5
6
7
var obj = {
    name : 'hello',
    target : 'world',
    say : function(what){
        return 'You said:' + what;
    }
};

Luaでは、meta tableというデータ構造を使っています。JSONに非常に似てるが、:の代わりに=を使います:

1
2
3
4
5
6
7
local obj = {
    name = 'hello',
    target = 'world',
    say = function(what)
        return 'You said:' .. what
    end
}

この=:に間違えて書いてもなかなか気づかない時があるので、つらいです(笑)。

OOP

JavaScriptとLuaにはClassというコンセプトがないですが、それぞれ自分の独自の方法でClassらしいオブジェクトが作れます。

JavaScriptはprototypeを利用してClassを作っています:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var MyClass = (function(){
    // construct
    function MyClass(params)
    {
        this.params = params || {};
    }

    // instance method
    MyClass.prototype.getName = function()
    {
        return this.params.name || 'none';
    }

    // static method
    MyClass.create = function(params)
    {
        return new MyClass(params);
    }
    reutrn MyClass;
})();
var my_class = MyClass.create({ name : 'Hello' });
console.log(my_class.getName()); // Hello

Luaの場合は

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
local myClass = {}

// constructor
function myClass:new(params)
    local p = params or {}
    setmetatable(p, self)
    self.__index = self
    return p
end

// instance method
function myClass:getName()
    return self.name or 'none'
end

// static method
function myClass.create(params)
    return myClass:new(params)
end

local my_class = myClass.create({ name = 'Hell' })
print(my_class:getName()) // 'Hello'

Lua一番ややこしいところは.:の区別です。理論的には簡単ですが、なんか文法が中途半端ですごい間違えやすいです:

1
2
3
4
5
6
7
function Class.method(self)
    return self.name
end
function Class:method()
    return self.name
end
// 上記の二つのメーソドは同じものです。「:」を使うと、第一引数にオブジェクト自身のインスタンスが渡され、メソード内selfで呼び出せます。

まとめ

この記事は単純に趣味でLuaとJavaScriptを比較してみただけです。あまり意味ないかもしれないけど、JavaScript経験者がLuaを学べる参考になると嬉しいです。