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

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

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

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

Q&A

解決済

5回答

10713閲覧

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

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

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

0グッド

3クリップ

投稿2016/06/10 04:06

編集2016/06/10 16:12

知りたいことリスト

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

質問者の理解度

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

わかってないこと

JSのGCの仕組み

ベストアンサーについて

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

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

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

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

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

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

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

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

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

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


voidは演算子
です。

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

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

html

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

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

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

投稿2016/06/10 05:55

編集2016/06/10 07:05
hidekichi

総合スコア366

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/10 06:33

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

2016/06/10 07:02

例で言うと短く書けるのと、void(0)はundefinedなので、未定義のものには何もしないというのもあるかと思います。 aタグはリンクとして表示し(使い)たいけれども、aタグの動作はさせないようにしたいと言う感じでしょうか。再読み込みとか。 もしundefinedが何かしらに上書きされた場合、変更されたものを表示したりします。ここから、まぁundefinedは上書きされる恐れがあるので、voidは演算子で必ずundefined(未定義)を返すことから、一番簡単に書けるのはvoid(0)なので、それでいいじゃないって感じかと思います。 ようはundefinedを信用するなと言うことをvoid(0)で表しているんですかね。 ちなみに「functionキーワード...」の部分は、void(0)がundefinedを返すと言うような意味を日本語訳した人がそう解釈したんですかね。何となしに僕は「void(0)がundefinedを返す」というのを想像しましたが、わかりにくい日本語ですよね(笑)
退会済みユーザー

退会済みユーザー

2016/06/10 16:08

より,安全で信頼された undefined を求めて void 0 を使うことがあるということがよく理解できました.ありがとうございます. 質問前は,それぞれ,演算子,リテラル,プロパティであることを理解していなかったため混乱につながったのだと思います. javascript を書いていても 現代っ子でこういう背景をしらなかったので大変勉強になりました.
guest

0

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が返る

投稿2016/06/10 04:51

yambejp

総合スコア114829

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

null

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

javascript

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

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

javascript

1console.log('hoge'.match(/foo/)); // null 2console.log(document.getElementById('hoge')); // null 3console.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 を参照できますが、記述が長く、扱いやすいとは言えません。

javascript

1(function () { 2 var undefined = true; 3 4 console.log(Function('return this')().undefined); // undefined 5}());

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

javascript

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

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

void 演算子

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

javascript

1(function () { 2 var undefined = true; 3 var a; 4 5 console.log(a === void 0); // true 6 console.log(typeof a === 'undefined'); // true 7}());

typeof 演算子

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

javascript

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

Re: MaxMellon さん

投稿2016/06/10 14:32

think49

総合スコア18162

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/10 16:06

コード例,利用例を事細かく記述していただきありがとうございます. リテラルと演算子とプロパティの違いが質問前よりはっきりと理解できるようになりました. typeof 演算子を利用する目的まで丁寧にありがとうございます.
guest

0

ベストアンサー

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/10 13:00

編集2016/06/10 13:02
raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/10 16:27 編集

わかりやすい回答ありがとうございます. 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 に入りますか?
maisumakun

2016/06/10 21:56

strictモードでも、ローカル変数としてのundefinedは定義可能なままとなっています(むろん、undefined値以外を代入すれば大混乱となるのは目に見えてますが)。 あと、ガベージコレクタですが、要はオブジェクトへの参照がなくなればそのオブジェクトがGCの対象になるので、undefinedだろうがnullだろうが0だろうが構いません。そして、JavaScriptの規格内ではGCについて何も定義されていないので、極端な話「メモリは全て使い捨てで再利用しない」処理系があるかもしれません。
raccy

2016/06/10 23:24

ローカル変数にしてしまうは盲点でした。`var undefined;`とする人がいるのかもありますが、何を改良しても中途半端で駄目なのがJavaScriptなんでしょうかねー。Webにおける機械語としてしか生き残っていく手段は無いような気がします。 昔のJavaScript処理系では、GCに参照カウントしか実装されて無く、循環参照が全く回収されないという致命的な問題がありました(現在の主要な処理系は大丈夫です)。そのため、使い終わったらとりあえずdeleteというのが流行っていたと思います。昔のPHP(これも参照カウントしかなかった)のunsetせよと同じです。現在は、変数のスコープや寿命を意識すべきと言う考えが主流であり、deleteはおろかdeleteの代わりにvoid 0代入は逆に混乱の元と言えるかと思います。 ※ 現在もDOMとの連携で循環参照になり、メモリリークが発生するパターンがあるようですが、それはまた別の問題かと思います。
guest

0

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 04:43

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/06/10 04:49

> undefinedであることをチェックする場面は多いかもしれませんが、自分から代入したい時にはnullを使うのが一般的 これって,なにか具体的な理由が存在するのですか?それとも,代入時は代入していることがパット見でわかるように `null` を使うようになっているのが一般的なだけなのですか? > undefinedという名前の変数を自分で定義できるので、そのままundefinedと書いていると値が変わってしまう危険がある これについてはすごく納得しました. このコメントを見た限り, - undefined を代入するのは一般的ではない - 代入時は null を 代入することが多い. - null ではなく undefined を入れたい時は, void 0 で入れる ということでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問