JavaScript おれおれ Advent Calendar 2011 – 3日目

演算子というと+とか=とか&&とか記号が思い浮かぶんじゃないかと思うんですが、アルファベットで構成される演算子っていうのもあるんですよね。ちょいとまとめてみます。

  • new
  • delete
  • typeof
  • void
  • instanceof
  • in

順に見て行きましょう。

new演算子

インスタンスを作る奴ですね。jQueryでもりもり作るような場合にはまず見ないと思うんですが、もっとこうプログラマーちっくにごりごり作る場合にはよく使ったりします。

// MyClassのインスタンスを作成する
var obj = new MyClass();

newという演算子はクラスからインスタンス(そのクラスの実体であるオブジェクト)を作成する……というのが一般的な動作です。が、JavaScriptは違います。そのそもクラスというものは存在しません。先の例のMyClassはクラスではなくコンストラクターです。

まあこのあたりの話はまたいずれ、詳しくお話させて頂こうと思っています。

delete演算子

オブジェクトのプロパティを削除します。

var obj = { a: 1, b: 2 };
console.log(obj.a);  // => 1

delete obj.a;
console.log(obj.a);  // => undefined

削除されたプロパティは参照できないので、undefinedになります。

じゃあ、undefinedを代入するのと何が違うのでしょう?

undefinedを代入した場合は、あくまでその値が代入されているだけで、プロパティは残ります。この状態ではin(後述)やfor inで表示されてしまいます。もちろんconsole系で羅列した場合も表示される事になります。

var a, p, obj;

obj = { a: 1, b: 2 };
delete obj.a;
a = [];
for (p in obj) {
  a.push(p);
}
console.log(a.join());  // => b

obj = { a: 1, b: 2 };
obj.a = undefined;
a=[]
for (p in obj) {
  a.push(p);
}
console.log(a.join());  // => a, b

またプロトタイプチェインにプロパティがある場合は、自身のプロパティを削除する事でそちらが得られるようになります。

function MyClass() {}
MyClass.prototype.a = 123;

// 自身のプロパティを持たないオブジェクトを作成
var obj = new MyClass();
console.log(obj.a);  // => 123


// 自身のプロパティを作成
obj.a = 999;
console.log(obj.a);  // => 999

// 自身のプロパティを削除
delete obj.a;
console.log(obj.a);  // => 123

typeof演算子

対象の型を文字列で返します。

結果
undefined "undefined"
真偽値 "boolean"
数値 "number"
文字列 "string"
関数 "function"
null "object"
オブジェクト "object"

数値はNaNInfinityも含みます。

またnew String()で得られるものは文字列ではなくStringオブジェクトであるので、"object"になります。

undefinedの扱いはちょっと例外的

var a;
console.log(typeof a);  // "undefined"
console.log(typeof b);  // "undefined"
console.log(a);  // "undefined"
console.log(b);  // ReferenceErrorが投げられる

未定義の変数を参照するとReferenceErrorになるのが普通ですが、typeofはエラーにせず"undefined"を返します。

一方定義済みだが値が未定義である変数も同様に"undefined"を返します。

typeof null"object"になるのは、実は最初期のただのミス

You know, this all came about because of rushing in early May 1995, which led to a leak of type tag representation shared by null and object types. But null means “no object”, so it didn’t raise hackles until it was too late to fix in Netscape 2, and after that we were loath to “fix” it and “break the web”.

参考

void演算子

右辺を評価後に破棄し、常にundefinedを返します。

var a = 1;
console.log(void (a+=1));  // => undefined
console.log(a);  // => 2

処理自体は行われますので、上記の例では加算を行った後にundefinedが返ります。

ブックマークレットを作る場合にはよく利用されてます。他で使う場面もあるんでしょうか?

instanceof演算子

右辺が左辺のインスタンスであればtrueを、そうでなければfalseを返します。

function MyClass() {}

var obj = new MyClass();
console.log(obj instanceof MyClass);  // => true

var obj = {};
console.log(obj instanceof MyClass);  // => false

右辺が実行可能でないとTypeErrorが投げられます。

コンストラクターがnew付きで呼ばれたかどうかを判定する場合にも使えます。

function MyClass() {
  console.log(this);
  if (!(this instanceof MyClass)) {
    return new MyClass();
  }
}

MyClass();
new MyClass();

newなしで実行すると実行コンテキストがwindow等のグローバルオブジェクトになってしまいます。this.prop = 123のようにプロパティ定義を行ったつもりが、グローバル変数を設定する事になってしまうわけです。

in演算子

右辺で与えられるオブジェクトが左辺で与えられる名前のプロパティを持っていればtrue、そうでなければfalseを返します。

function MyClass() {}
MyClass.prototype.a = 123;

var obj = new MyClass();
obj.b = 456;

console.log("a" in obj);  // => true
console.log("b" in obj);  // => true
console.log("c" in obj);  // => false

プロパティが自身のプロパティであるか、プロトタイプチェイン上のプロパティであるかは問いません。それを判定する場合は .hasOwnProperty()を利用します。

console.log(obj.hasOwnProperty("a"));  // => false
console.log(obj.hasOwnProperty("b"));  // => true