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

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

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

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

JavaScript

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

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

2回答

6842閲覧

「return; と return undefined; が同じではない」とは?

think49

総合スコア18164

ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

JavaScript

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

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

0グッド

0クリップ

投稿2016/11/02 05:45

return; と return undefined; が同じではない

下記スレッドにおいて raccy さんが次のように回答されています。

JavaScriptにおいてreturn;return undefined;が同じではないのと同じく、CoffeeScriptではreturnreturn undefindは同じではありませんが、結果だけを見ると、CoffeeScriptは両方ともundefind値を返すという同じ動作になります。

コード

JavaScript

1function sample1 () { 2 // return を書かない 3} 4 5function sample2 () { 6 return; 7} 8 9function sample3 () { 10 return undefined; 11} 12 13function sample4 () { 14 return void 0; 15} 16 17console.log(sample1()); // undefined (明示的に return しなかった場合の返り値の規定値は undefined である) 18console.log(sample2()); // undefined (return; は undefined を返す) 19console.log(sample3()); // undefined (グローバル変数 undefined は undefined を返す) 20console.log(sample4()); // undefined (void 演算子の評価値は常に undefined である)

検証の結果、評価値は全て同じとなりました。

undefined は予約語ではない

ES5 でグローバル変数 undefined は書き換え不可能になりましたが、ES7 (ES2016) でも undefined は Keywords に入ってない為、ローカル変数 undefined を定義して疑似的に書き換える事が可能です。

JavaScript

1(function (undefined) { // ローカル変数 undefined を定義する 2 console.log(undefined); // 1 3}(1));

質問

「JavaScriptにおいてreturn;return undefined;が同じではない」とは何の違いを表しているのでしょうか。
undefined の名前でローカル変数を定義できてしまう為、変数 undefinedundefined 値である事を保証できない」という意味でしょうか。

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

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

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

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

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

guest

回答2

0

ベストアンサー

たしかに、ローカル変数であればES5以降でもundefinedを定義できるため、return;return undefined;の挙動を違わせることは可能です。

javascript

1function evil(){ 2 var undefined = 5; 3 return { 4 return_only: function(){ return; } 5 return_undefined: function(){ return undefined; } 6 }; 7} 8 9console.log(evil().return_only()); // undefined 10console.log(evil().return_undefined()); // 5

あと、undefinedグローバル変数の1つですので、値を参照するにはスコープをたどる必要があります(もっとも、上のような真似をしていない限り得られる値は同じですのでJavaScript内から峻別する必要はあまりありませんし、最適化されれば動作速度の面でも有意な差は出ないと思います)。

投稿2016/11/02 12:26

maisumakun

総合スコア145184

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

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

think49

2016/11/02 13:22

やはり、思いつくのは undefined をスコープチェーン上で汚せる挙動になるでしょうか。 一応、全てのスコープに const で undefined を再定義すれば書き換えを防ぐことができますが、労力と対価が釣り合ってないので undefined が必要であれば void 演算子を使うことにしています。 https://jsfiddle.net/fzcnfc7u/ 仰る通り、ローカル変数 undefined を定義することは基本的にありえないので通常の運用では問題ないと思いますが、なんとも気持ち悪い仕様です…。
maisumakun

2016/11/02 13:25

おそらく、ES3時代に「グローバルのundefinedすら代入可能」だったことへの対策として「ローカルでundefined値の入ったundefinedを宣言しておく」ということが行われたために、ES5でローカルでのundefined宣言を禁止できなかった、ということではないかと思います(それでも代入は正当な用法としてはありえないでしょうが)。
think49

2016/11/02 13:50

その可能性はありそうですね。 個人的には「後方互換性は Non Strict Mode で確保すれば良かったのでは…」と素人考えながら思ってしまうのですが、Strict Mode でも Keywords の有無をスイッチするのは厳しかった、というところでしょうか。
raccy

2016/11/02 13:58

質問の元ネタの文章を書いた人の中の人曰く「この回答の通りです」だそうです。
think49

2016/11/02 14:05

To: raccy さん 返答ありがとうございます。これにて解決とします。
raccy

2016/11/02 14:13

というか、この質問に全然気付かなかったです…。 なお、このundefinedの謎の仕様をさけるために、CoffeeScriptではundefinedは全て`void 0`に変換するという動作になっています。
think49

2016/11/02 14:25

To: raccy さん 実は raccy さんに回答リクエストしようと思ったのですが、相互フォローしていないとリクエスト出来ないようでどうしようかと思っていました。件の回答にコメントする事も考えましたが、気が付いて頂けて良かったです。 > CoffeeScriptではundefinedは全て`void 0`に変換するという動作になっています。 いい仕様ですね!
guest

0

return;
では、文字通り、「未定義」としてのNullが返り、
return undefined;
では、「undefinedという、(今ここで)定義されたが中身のない変数」が返る、
つまり、undefinedの中身であるNullが返る、ということではないでしょうか。

投稿2016/11/02 06:09

akio221

総合スコア716

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

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

think49

2016/11/02 06:50 編集

「「未定義」としてのNull」と「中身のない変数」が曖昧でよくわかりません…。 ES7 仕様を読んでみましたが、null と undefined は別個に定義されていました。 しかし、今回はどちらも undefined 値であって違いはないように認識していたのですが、厳密には違いがあって何らかの動作に影響を与えているのでしょうか。 > 4.3.10 undefined value > 変数に値が割り当てられていない場合のプリミティブ値。 > http://www.ecma-international.org/ecma-262/7.0/#sec-undefined-value > 4.3.12 null value > 任意のオブジェクト値が意図的に存在しない事を表すプリミティブ値。 > http://www.ecma-international.org/ecma-262/7.0/#sec-null-value
akio221

2016/11/02 06:44

動作に影響があるのかどうかと言われると、そこまで気にしたことはないのですが・・。 私の理解でお話しすると、もうすこし、ハード寄りというかアドレス空間よりに、 return;でマシンが返すのは、返すポインタがない、という意味のundefinedで、 return undefined;では、一度、変数「undefined 」が指し示すポインタを見に行って、 その先の「undefined 」ポインタの中身、undefined を返していると考えます。 結果はどちらもundefined(Null)なのでしょうが。 例えば今後、言語仕様が変更されて、未定義変数をreturnしたとき、 必ず"hoge"が返されるようになれば、後者との差は非常に分かりやすいのですが。(^^;
akio221

2016/11/02 06:54

一度評価が入る、「等価演算子」==での比較では同一と判定され、 アドレス空間まで気にする「厳密等価演算子」===では異なる、と思います。 #手元で試していませんが、後者はポインタを経由するはずなので・・・。 あと、nullとundefinedを混ぜちゃってすみません。java屋なものですから・・。
think49

2016/11/02 07:20

私は逆にアドレスの知識がないものでその部分は理解できているといえませんが、「定義されたが中身のない変数」という表現を踏まえるとこういう事でしょうか。 例えば、ES6 の Map の Polyfill の作成中に Map.prototype.get のコードを書くケースを想定します。 Map.prototype.get は は存在しないキーが指定された場合に undefined を返す仕様ですが、この場合のコードは return; ではなく、return undefined; として明示的に undefined 値を指定したくなります。 挙動は同じですが、「明示的に undefined を指定する事」と「未指定にすることで暗黙的に undefined を指定する事」ではコードに与える意味が異なります。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Map/get 対して、addEventListener のイベントハンドラ関数で特定条件下で処理を強制終了させたい場合には return; を指定します。 return undefined; でも同じ挙動となりますが、この場合は返り値を指定する事に意味はなく、ただ単純に強制終了させるのが目的なので返り値は指定しません。 ただし、akio221 さんが懸念されているように return; の初期値が将来的に変更された場合、例えば return false; が初期値となった場合、return; でデフォルトアクション抑止が働く事となる為、「return undefined; を指定すべき」という判断に変わります。 その懸念を振り払うなら return undefined; を指定した方がいいのですが、私は return; の挙動が変更されることはないと考えています。 世のWebブラウザは少しずつ新しいブラウザに移り変わっていますが、今でも古いブラウザを使う人がいる事からECMAScriptの仕様は後方互換性を何よりも重視する傾向があると考えているからです。 (typeof null === 'object' のようないかにもバグらしい仕様が今でも残っているぐらいですから…。) > 一度評価が入る、「等価演算子」==での比較では同一と判定され、アドレス空間まで気にする「厳密等価演算子」===では異なる、と思います。 undefined はプリミティブ値ですので値比較ですね。Object 型(Reference 型)のように参照比較はされません。 (function () { return; }()) === (function () { return undefined; }()); // true
akio221

2016/11/02 07:43

ちょっと反省してMDN見てきました。結果、私の認識が間違っていました。 まず、undefinedが、 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/undefined#Strict_equality_and_undefined >まだ値が代入されていない変数は undefined 型となります。 >また、評価されようとしている変数が代入値を持たない場合、 >メソッドや文は undefined を返します。 >return 文がなく値を返さない関数も undefined を返します。 と、あり、続いてreturnが、 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/return >return [[expression]]; > >expression > 返す式。もし省略されたなら、undefined が代わりに返ります。 とあります。同じプリミティブなundefined を返すので等価です。
think49

2016/11/02 07:57

わかりました。 やはり、raccy さんの回答を待つことにします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問