質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • JavaScript

    18626questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

void 0, undefined, null の 違いを教えて下さい

解決済

回答 5

投稿 編集

  • 評価
  • クリップ 3
  • VIEW 3,048

MaxMellon

score 1001

 知りたいことリスト

  • GC時の扱いが異なるのか?また異なるのはなぜか?
  • undefined = true  //=> true となるのは何がいけないのか?
  • CoffeeScript などをトランスパイルした時,undefined や null が void 0 に置換されるのはなぜか?
  • hoge = void 0 と hoge = null と hoge = undefined の違いは何か?
  • 結局,コーディング時は何に統一するのが良いのか?

 質問者の理解度

null !== undefined   //=> true
null == undefined    //=> true
void 0 === undefined //=> true
undefined = true // => true

 わかってないこと

JSのGCの仕組み

 ベストアンサーについて

皆様大変丁寧な回答有り難うございます.

javascript の 歴史や,こういった仕様になった背景を知ろうとするきっかけになり大変勉強になりました.

回答者全員にベストアンサーを送りたいと考えているのですが,残念ですが1名にしか送ることができません.

僕なりに,ベストなアンサーは何か?ということを考えた結果.
僕の疑問点に対して,網羅的に回答しかつ,余談や OSS での例などに触れられてわかりやすいだけでなく興味深い回答をしてくださった raccy さんに ベストアンサーを送りたいと思います.

皆様,大変わかり易い回答有り難うございました.

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

+4

undefined グローバルオブジェクトのプロパティで、つまりは値が未定義っと言う感じです。

nullはリテラルです。
NULL値または"空"値を返す感じです。

google先生曰く「リテラルとは、プログラムのソースコードにおいて使用される、数値や文字列を直接に記述した定数のことである。」

null === undefined // false
null  == undefined // true


これも面白いですよね。型チェックするとfalseになったり。


voidは演算子
です。

スクリプト全体を囲み、即座に実行が行われる関数式の際に、 voidはfunctionキーワードを宣言の代わりに、 式として扱うように強制することに使用出来ます。

トランスパイルしてvoid(0)が入るのは、こういう理由からではないですかね?
トランスパイルをあんまりしないので、ちゃんと読んでないんですけど(笑)

<a href="javascript:void(0);">クリックしても何も起こらない</a>
<a href="javascript:void(document.body.style.backgroundColor='green');">
  ここをクリックすると背景が緑になります。
</a>


こういうのたまに見かけますよね。

ここらは重要な点ですが、わかりにくい部分であるのも確かです。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/10 15:33

    式として扱うように強制すること のメリットは何ですか?

    キャンセル

  • 2016/06/10 16:02

    例で言うと短く書けるのと、void(0)はundefinedなので、未定義のものには何もしないというのもあるかと思います。
    aタグはリンクとして表示し(使い)たいけれども、aタグの動作はさせないようにしたいと言う感じでしょうか。再読み込みとか。

    もしundefinedが何かしらに上書きされた場合、変更されたものを表示したりします。ここから、まぁundefinedは上書きされる恐れがあるので、voidは演算子で必ずundefined(未定義)を返すことから、一番簡単に書けるのはvoid(0)なので、それでいいじゃないって感じかと思います。

    ようはundefinedを信用するなと言うことをvoid(0)で表しているんですかね。

    ちなみに「functionキーワード...」の部分は、void(0)がundefinedを返すと言うような意味を日本語訳した人がそう解釈したんですかね。何となしに僕は「void(0)がundefinedを返す」というのを想像しましたが、わかりにくい日本語ですよね(笑)

    キャンセル

  • 2016/06/11 01:08

    より,安全で信頼された undefined を求めて void 0 を使うことがあるということがよく理解できました.ありがとうございます.

    質問前は,それぞれ,演算子,リテラル,プロパティであることを理解していなかったため混乱につながったのだと思います.

    javascript を書いていても 現代っ子でこういう背景をしらなかったので大変勉強になりました.

    キャンセル

+2

nullは空というオブジェクト
undefinedは未定義状態なのでオブジェクトですらない
void 0はundefinedを返す演算子(?)

じゃ、undefinedとvoid 0は等価かというと、
undefinedはnullのような予約語ではないので代入ができる

undefined="hogehoge"


代入されたundefined変数は、ブラウザによって代入値を返す場合もあるし
undefinedを返す場合もあるようなあいまいな状況
したがって制度を高めるためにundefinedをチェックするときにはvoid 0を利用する。

以下順に
null !== undefined   //=> true
※オブジェクトと未定義を厳密に比較しているのでfalse

null == undefined    //=> true
※空と未定義をあいまいに比較しているのでtrue

void 0 === undefined //=> true
undefinedとundefinedを厳密に比較しているのでtrue

undefined = true // => true 
単なる代入式なので成功すればtrue

チェックにはtypeofを利用するとよい
document.write(typeof null);
document.write(typeof undefined);
document.write(typeof void 0);
document.write(typeof hogehoge);//事前に宣言されてなければundefinedが返る

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+1

GC時の扱いが異なるのか?また異なるのはなぜか?

GCは関係無いです。今回は。

undefined = true  //=> true となるのは何がいけないのか?

null = trueがエラーになると言う事実と整合性がとれていないように見えるからです。JavaScriptにおいてnull値undefined値は特別な値のように見えて、その扱いには差があります。null値を表現できるようにnullリテラルが与えられましたが、undefined値にはグローバルオブジェクトのundefindeプロパティしか直接の表現方法が与えられませんでした。そのため、undefinedプロパティは所詮プロパティに過ぎず、再代入が可能であり、常にundefined値であるという保証が無くなってしまいました。

しかし、ほとんどのプログラムにおいては、undefinedプロパティは、nullリテラルと同じように、常に同じundefined値であることが期待することが多く、再代入は無用なバグをうむ温床となり得ます。そこで、"use strict"による厳密モードではエラーになるようにし、この動作自体を非推奨としました。しかし、過去の互換という観点から、非厳密モードでは未だに可能であり、無用な混乱とバグを引き起こす原因の一つになり得ます。

※ 再代入によって実際に値が変わるかどうかは処理系によるようです。古い処理系では変わるようですが、node.js(v6.2.0)では変わりませんでした。

CoffeeScript などをトランスパイルした時,undefined や null が void 0 に置換されるのはなぜか?

undefinedプロパティundefined値であるという保証が無いからです。undefinedプロパティはグローバルオブジェクトのプロパティですので、現在のコードに再代入するようなコードが無くても、その他に読み込んだJavaScirptのコードに再代入するようなコードがあれば書き換わっている可能性があります。これを防ぐ方法はありません。

CoffeeScriptではundefinednullと同様の動きにする(つまり、再代入できないし、常にundefined値になる)としています。CocoやLiveScriptではvoidを常にundefined値になるリテラルとして定義しています。これらについて、値が保証されないundefinedプロパティは使えないため、必ずundefined値になるvoid 0void 8を使用します。なお、8は中国のラッキーナンバーだからです。

hoge = void 0 と hoge = null と hoge = undefined の違いは何か?

hoge = void 0は、hoge変数に、void 0を評価した結果であるundefined値を代入します。
hoge = nullは、hoge変数に、null値を代入します。
hoge = undefinedは、hoge変数に、現在のundefinedプロパティ(必ずしもundefined値とは限らない)を代入します。

結局,コーディング時は何に統一するのが良いのか?

undefinedプロパティに再代入するようなコードは極めて行儀悪いコードであり、滅多に無いと推測されます。また、品質的にも、そのようなコードが含まれるライブラリ等を使うべきではありません。

自分の書いたコードについては、"use strict"による厳密モードを強制することで、そのようなコードを書いてしまうことを防ぐことができます。"use strict"は絶対に書くべきですし、他にも多くの恩恵を受けることができます。

このようにしてundefinedをそのまま用いてもほとんどの場合は問題が出ることは少ないでしょう。ただ、問題が出たときは、一目では理解不能なバグに見えてしまうため、苦労をする可能性があります。

私のお勧めは「生のJavaScriptを使わない」です。CoffeeScriptやLiveScriptを使えば、このような理不尽な仕様に悩む必要はありません。teratailで回答するための検証等をのぞき、私は生のJavaScriptを書くことはもう無いと思っています。JavaScriptを捨てて今すぐaltJSを使うべきであり、それこそが、真のJSerへの道だと私は思っています。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/11 00:58 編集

    わかりやすい回答ありがとうございます.
    void 8 などの豆知識など事細かく書かれており非常に参考になりました.

    GCについて掲載したのは,
    http://blog.livedoor.jp/aki_mana/archives/2587785.html
    このサイトで,void 0 の代入は delete と同じ効果をもたらすと記述されていたからです.

    void 0 を代入することで,undefined が代入され GC の対象になりメモリが開放されると解釈していました.この理解が間違っている場合指摘いただけると大変嬉しいです.

    >「生のJavaScriptを使わない」

    これについては完全に同意です.
    https://www.npmjs.com/package/babel-plugin-undefined-to-void
    などを使って安全にjavascript を書くライフを満喫したいと思います.

    先生,babel は altJS に入りますか?

    キャンセル

  • 2016/06/11 06:56

    strictモードでも、ローカル変数としてのundefinedは定義可能なままとなっています(むろん、undefined値以外を代入すれば大混乱となるのは目に見えてますが)。

    あと、ガベージコレクタですが、要はオブジェクトへの参照がなくなればそのオブジェクトがGCの対象になるので、undefinedだろうがnullだろうが0だろうが構いません。そして、JavaScriptの規格内ではGCについて何も定義されていないので、極端な話「メモリは全て使い捨てで再利用しない」処理系があるかもしれません。

    キャンセル

  • 2016/06/11 08:24

    ローカル変数にしてしまうは盲点でした。`var undefined;`とする人がいるのかもありますが、何を改良しても中途半端で駄目なのがJavaScriptなんでしょうかねー。Webにおける機械語としてしか生き残っていく手段は無いような気がします。

    昔のJavaScript処理系では、GCに参照カウントしか実装されて無く、循環参照が全く回収されないという致命的な問題がありました(現在の主要な処理系は大丈夫です)。そのため、使い終わったらとりあえずdeleteというのが流行っていたと思います。昔のPHP(これも参照カウントしかなかった)のunsetせよと同じです。現在は、変数のスコープや寿命を意識すべきと言う考えが主流であり、deleteはおろかdeleteの代わりにvoid 0代入は逆に混乱の元と言えるかと思います。
    ※ 現在もDOMとの連携で循環参照になり、メモリリークが発生するパターンがあるようですが、それはまた別の問題かと思います。

    キャンセル

+1

JavaScriptのvoidは1引数の演算子で、void 0だろうがvoid 100だろうがvoid 'hello world'だろうが、常にundefined値を返します。

undefinedの代わりにvoid 0と書くメリットは以下のものがあります。

  • 文字数が3文字少ない
  • undefinedという名前の変数を自分で定義できるので、そのままundefinedと書いていると値が変わってしまう危険がある

そして、null == void 0かつnull !== void 0です。

undefinedであることをチェックする場面は多いかもしれませんが、自分から代入したい時にはnullを使うのが一般的です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/10 13:49

    > undefinedであることをチェックする場面は多いかもしれませんが、自分から代入したい時にはnullを使うのが一般的

    これって,なにか具体的な理由が存在するのですか?それとも,代入時は代入していることがパット見でわかるように `null` を使うようになっているのが一般的なだけなのですか?

    > undefinedという名前の変数を自分で定義できるので、そのままundefinedと書いていると値が変わってしまう危険がある

    これについてはすごく納得しました.

    このコメントを見た限り,

    - undefined を代入するのは一般的ではない
    - 代入時は null を 代入することが多い.
    - null ではなく undefined を入れたい時は, void 0 で入れる

    ということでしょうか?

    キャンセル

+1

 null

null はキーワードなので再代入を許しません。

null = true;  // ReferenceError: Invalid left-hand side in assignment

null はオブジェクトが存在しないことを表します。
例えば、String#match ではマッチしなかった場合に、getElementById では対象のIDを持つ要素が存在しなかった時に、document.onclick では onclick イベントハンドラが存在しない時に null を返します。

console.log('hoge'.match(/foo/));  // null
console.log(document.getElementById('hoge'));  // null
console.log(document.onclick);  // null

 undefined

undefined はグローバル変数です。
ES5 からグローバル変数 undefined は書き換え不可能となりましたが、キーワードではないのでローカル変数 undefined を定義することが出来てしまいます。

'use strict';
(function () {
  var undefined = true;

  console.log(undefined); // true
  console.log(Function('return this')().undefined); // undefined
}());

console.log(undefined); // undefined
undefined = true; // TypeError: Cannot assign to read only property 'undefined' of object '#<Window>'

一応、グローバルオブジェクトを辿れば、グローバル変数 undefined を参照できますが、記述が長く、扱いやすいとは言えません。

(function () {
  var undefined = true;

  console.log(Function('return this')().undefined); // undefined
}());

undefined はシステムが未定義と判断した時に返す値です。
例えば、未定義のプロパティを参照した場合に undefined を返します。

console.log({}[0]); // undefined

その為、一般的にオブジェクトのプロパティに undefined を代入するコードは書きません。
未定義のプロパティと区別がつかないからです。
(厳密には in 演算子や Object#hasOwnProperty で判断することが可能ですが、そうするだけのメリットがありません。)

 void 演算子

void 演算子は常に undefined を返す為、グローバル変数 undefined よりは扱いやすいといえます。

(function () {
  var undefined = true;
  var a;

  console.log(a === void 0); // true
  console.log(typeof a === 'undefined'); // true
}());

 typeof 演算子

typeof 演算子は存在しない変数を例外を発生させる事なく判定することが可能です。

console.log(typeof hoge === 'undefined'); // true
console.log(hoge === void 0); // ReferenceError: hoge is not defined

Re: MaxMellon さん

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/11 01:06

    コード例,利用例を事細かく記述していただきありがとうございます.

    リテラルと演算子とプロパティの違いが質問前よりはっきりと理解できるようになりました.

    typeof 演算子を利用する目的まで丁寧にありがとうございます.

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • JavaScript

    18626questions

    JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。