比較言語学

JavaScript ご存知の方には面白くない話だと思うので無視してください。ただの備忘録です。
JavaScript では、以下の 3つが区別されます。

  • 変数に null が代入されている状態
  • 変数が「undefined である」状態
  • 変数が「宣言されていない」状態

面白い言語ですね。明示的に宣言していない変数に値を代入すると、その時点でグローバル変数として宣言されたことになるくせに、しかし宣言されていない変数を評価するとエラーになります。つまり宣言していない変数は、undefined ではない訳ですね。変数に型のない言語で有名(?)なものに AWK がありますが、AWK では宣言していない変数*1を評価すると、あたかも null のように扱われます。数値コンテキストで評価すると 0 になりますし、文字列コンテキストで評価すると "" になります。この点で、AWKJavaScript は異なります。
また、変数がブロックスコープを持たない点と、関数中のいずれかの箇所で宣言したローカル変数が、宣言箇所よりも前でも有効というのも面白い特徴です。つまり、

var a = 3;
function foo()
{
    document.write(a);
    var a = 5;
    document.write(a);
}

foo();

とすると、最初の document.write() では "undefined" が表示され、後者では 5 が表示されます。
でも、よくよく考えてみると、これって Python と同じかも。Python では、次のコードを実行すると foo() の評価でエラーになります。(最初の print で、UnboundLocalError: local variable 'a' referenced before assignment になります。)

a = 5
def foo():
    print a
    a= 7
    print a

foo()

ちなみに Python では、global キーワードで強制的にグローバル変数をアクセスできるけど、JavaScript で同じことをするには、関数内で var キーワードで宣言しなければ良いのか。なるほど。つまり Python ならば

a = 5
def foo():
    global a
    print a
    a= 7
    print a

foo()
print a

JavaScript ならば、

var a = 5;
function foo()
{
    document.write(a);
    a = 7;
    document.write(a);
}

foo();
document.write(a);

ですね。
参考: Python のスコープについて

重箱の隅

JavaScript 1.2 時代(?)には、クラスの継承には prototype.__proto__ を使えとありますが、ECMA 標準では盛り込まれていないようです。どうしたらいいんだ? あ、古いバージョンの JavaScript では読み出し専用だった constructorが単に書き換え可能になっただけかー。つまり、こういうことね。

// This is a superclass.
function Human(name, sex)
{
    this.name = name;
    this.sex = sex;
}

Human.prototype.getName = function() {
    return this.name;
}

// This is a subclass of the superclass.
function Employee(name, sex, title)
{
    this.name = name;
    this.sex = sex;
    this.title = title;
}

Employee.prototype = new Human();
Employee.prototype.constructor = Employee;  // This recovers its constructor
                                            // property.

Employee.prototype.getTitle = function() {
    return this.title;
}

john = new Human("John", "male");
document.write("His name is " + john.getName() + ".<br>");
kate = new Employee("Kate", "female", "director");
document.write("Her name is " + kate.getName() + ".<br>");
document.write("Her job title is " + kate.getTitle() + ".<br>");
// document.write("His job title is " + john.getTitle() + ".<br>");  // Error
document.write("Constructor is '" + kate.constructor.toSource() + "'.<br>");

この辺にも書いてありました。
参考: http://www.quantumwave.com/flash/inheritance.html

配列

JavaScript では、多次元配列はサポートされないそうな。明示的に、配列オブジェクトの配列としてやらなければならないらしい。まだ、ちゃんと本読んでないんだけど、こんな感じかな、と、でっち上げてみました。

var a = new Array();
for (var i = 1; i <= 9; i ++) {
    a[i] = new Array();
    for (var j = 1; j <= 9; j ++) {
        a[i][j] = i * j;
    }
}

document.write("<table border=\"1\">");
for (var i = 1; i <= 9; i ++) {
    document.write("<tr align=\"right\"");
    for (var j = 1; j <= 9; j ++) {
        document.write("<td>" + a[i][j] + "</td>");
    }
    document.write("</tr>\n");
}
document.write("</table>");

すいません。間違ってたら許して。HTML も少し怪しいけど許して。

*1:AWK では変数を明示的に宣言する構文がないけど。