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

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

Lua

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

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

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

文法の違い

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

if文

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

var ok = true;
if (ok) {
console.log('OK');
} else {
console.log('Ops');
}

Luaの場合:

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のフォーマットでオブジェクトが作成できます:

var obj = {
name : 'hello',
target : 'world',
say : function(what){
return 'You said:' + what;
}
};

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

local obj = {
name = 'hello',
target = 'world',
say = function(what)
return 'You said:' .. what
end
}

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

OOP

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

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

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の場合は

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

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

まとめ

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