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

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

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

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

関数

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

Q&A

解決済

4回答

5599閲覧

関数と変数の巻き上げの違いとは

aaaaaaaa

総合スコア501

JavaScript

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

関数

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

0グッド

1クリップ

投稿2016/04/21 11:32

javascriptは、ほかの言語と違い関数内に宣言された局所変数は、関数内全体で有効なので宣言前でもundefindになりますが呼び出せます。ただ、解かりやすくするため、関数の最上部で宣言しますが
javascript以外は、その変数を利用するときに宣言するようです。これを変数の巻き上げといいますが、とあるサイトに「関数の巻き上げ」なる用語を使用しているサイトを見つけました。
書籍やネットを探っても、変数の巻き上げ以外に巻き上がるものは記述されておりませんでした。
そのサイトの文章を見てもいまいちなにを言っているのか分かりません。関数の巻き上げとはいったい何なのでしょうか。
http://d.hatena.ne.jp/kousukekayo/20090827/1251363441

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

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

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

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

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

guest

回答4

0

tkturbo さんの例を利用させていただくと、次のようになることかと。

javascript

1beforeHoge(); // (1) beforeHoge の定義文より前に呼び出し文が書ける 2 3function beforeHoge() { 4 hoge('定義前に呼んでもエラーにならない'); 5} 6 7function hoge(msg) { 8 console.log(msg); 9} 10 11beforeHoge(); // (2) もちろんここでも実行できる

tkturbo さんの例だと、beforeHoge() の実行部分が書いてありません。beforeHoge() の定義部分cで hoge() を実行するコードが書かれていますが、まだ実行はされていないわけで、もし、(2) の位置で beforeHoge() を実行するのであれば、そのときまでに hoge() の定義は済んでいるわけですから、「巻き上げ」の説明にはなっていないと思います。

ちなみに、function なら巻き上げが発生しますが、function だと巻き上げは発生しません。

javascript

1beforeHoge(); // (3) ここで TypeErro 発生 2 3var beforeHoge = function () { 4 hoge('定義前に呼んでもエラーにならない'); 5} 6 7function hoge(msg) { 8 console.log(msg); 9} 10 11beforeHoge(); // (4) これは実行できる

(3) のところでは、「変数の巻き上げ」によって、beforeHogeundefined ではありますが、変数としては存在しています。しかし、undefined は関数オブジェクトではないので () をつけて実行しようとすると、「beforeHoge is not a function」とかの TypeError になります。で、(3) をコメントアウトしてみると、(4) はエラーなく実行されます。
念のため繰り返しますが、function文で関数を定義した場合には、(1) のように、その定義文の前に実行できる、すなわち、beforeHoge という名前で関数オブジェクトにアクセスできる、というのが「関数の巻き上げ」です。

投稿2016/04/21 13:09

unau

総合スコア2468

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

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

think49

2016/04/21 15:37

> ちなみに、function文 なら巻き上げが発生しますが、function式 だと巻き上げは発生しません。 少し前からいおうかいうまいか迷っていたのですが、誤解が生まれるといけないのでやはり指摘しておきます…。 ES3 から ES6 に至るまで「function 文」の定義は存在しません。 「function 文」の出所はおそらく、MDN だと思いますが、MDNは ES 仕様にそぐわない翻訳をする事もあるので参考情報に留めておく事をお勧めします。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/function その文脈で説明するならば「function 文」は「関数宣言(FunctionDeclaration)」に置き換えるのが適切だと思われます。 http://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions 一応、Syntax の ABNF に FunctionStatementList が存在しますが、関数コードの構成要素として定義されており、Statement には含まれません。 http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-statements-and-declarations あえて「文(Statement)」を出すとすれば式文(ExpressionStatement)の中で「関数式(FunctionExpression)」を含める事ができる事でしょうか。
unau

2016/04/21 21:55

ご指摘ありがとうございます。 こういう風に質問があって、それにあやふやでもいいから回答があって、そこにツッコミが入って、最終的に全体としてより役に立つ、より正しい情報ができあがる、というのがこういうソーシャルメディア的なもののよいところだと思っています。他の方に敬意を払えない(質問態度が悪い、検証・裏付けのさぼりなど)ことへの免罪符になっていはいけないと思いますが、質問も回答も、臆することなくでき、また、そこに臆することなくコメントできる、teratail にそういう文化が醸成されることは喜ばしいことであり、think49 さんがツッコミを入れてくださったことはそういう意味でもたいへん嬉しいです。 ECMAScript をしっかり勉強したことはなくて、ES6 にキャッチアップするのはしんどいなあ、と思っているロートルですので、提示していただいたリンク先を全部読んでちゃんと理解して、というのはやや厳しい気がしていますが、少なくともより正しい用語を使うように努めます。あと、過去に私が「function 文」と言及している回答には、(できるかぎり)ここの think49 さんのコメントを参照するよう、追加のコメントを付けてまわろうと思います。
guest

0

ベストアンサー

変数の巻き上げ(Variable hoisting)

var で変数宣言されたローカル変数(関数式)は関数スコープで巻き上げ(hoisting)されます。
(関数やグローバルコードが実行コンテキストに入る時に var 宣言された全ての変数を undefined で実体化します)。

JavaScript

1'use strict'; 2console.log(variableExpression); // undefined 3 4/** 5 * 関数式(VariableStatement) 6 */ 7var variableExpression = function variableExpression () {}; 8 9console.log(variableExpression); // function variableExpression() {}

let, const 文は巻き上がらない

let, const で宣言されたローカル変数(関数式)は宣言前に参照を試みると ReferenceError の例外を返します(ES6 規定)。

JavaScript

1'use strict'; 2console.log(letExpression); // ReferenceError: letExpression is not defined 3console.log(constExpression); // ReferenceError: constExpression is not defined 4 5/** 6 * 関数式(LexicalDeclaration) 7 */ 8let letExpression = function letExpression () {}; 9const constExpression = function constExpression () {};

関数宣言(FunctionDeclaration)の巻き上げ

関数宣言(FunctionDeclaration)は関数スコープで巻き上げられます。

JavaScript

1'use strict'; 2console.log(declaration); // function declaration () {} 3 4/** 5 * 関数宣言(FunctionDeclaration) 6 */ 7function declaration () {}

[ES6] ブロックレベル関数宣言(block-level FunctionDeclaration)

ES6 から Strict Mode 限定でブロックスコープで巻き上げられる関数宣言を定義出来るようになりました(注: IE10- で未対応です)。

JavaScript

1'use strict'; 2console.log(blockedDeclaration); // ReferenceError: blockedDeclaration is not defined 3 4/** 5 * 関数宣言(Strict Mode ではブロックスコープ) 6 */ 7if (true) { 8 console.log(blockedDeclaration); // function blockedDeclaration() {} 9 function blockedDeclaration () {} 10} 11 12console.log(blockedDeclaration); // ReferenceError: blockedDeclaration is not defined

「非Strict Mode (sloppy mode)」では関数スコープで巻き上げられます。

JavaScript

1console.log(blockedDeclaration); // undefined 2 3/** 4 * 関数宣言(sloppy mode では関数スコープ) 5 */ 6if (true) { 7 console.log(blockedDeclaration); // function blockedDeclaration() {} 8 function blockedDeclaration () {} 9} 10 11console.log(blockedDeclaration); // function blockedDeclaration() {}

FunctionStatement
@nanto_vi さんは if 文内で条件付関数宣言する動作が Firefox 独自拡張だった頃に便宜上の名称として FunctionStatement (function 文) と説明しました。
便宜上の名称なので仕様上は「文」ではないのですが、ブロックスコープ単位で評価するこの動作は Statement に性質が近いので言い得て妙だと思います。

[ES5] ブロックレベル関数宣言で SyntaxError

ES5 の Strcit Mode ではブロックレベル関数宣言は SyntaxError を返す仕様でした。
「Windows Vista のサポート終了日(2017/04/11)」まではブロックレベル関数宣言の利用を控えた方がいいかもしれません。

JavaScript

1'use strict'; 2 3if (true) { 4 function blockedDeclaration () {} // SyntaxError 5}

更新履歴

  • 2016/04/22 01:55 ブロックレベル関数宣言(block-level FunctionDeclaration)の説明追加
  • 2016/04/22 02:25 ES5 (Strict Mode) ではブロックレベル関数宣言が SyntaxError になる

Re: aaaaaaaa さん

投稿2016/04/21 16:05

編集2016/04/21 17:29
think49

総合スコア18164

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

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

0

javascript

1function beforeHoge() { 2 hoge('定義前に呼んでもエラーにならない'); 3} 4 5function hoge(msg) { 6 console.log(msg); 7} 8 9function afterHoge() { 10 hoge('定義後に呼んでもエラーにならない'); 11}

こういうことでは?

投稿2016/04/21 12:30

tkturbo

総合スコア5572

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

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

0

「関数の巻き上げ」とは、スコープに関することで、

と説明されているようですが?

投稿2016/04/21 12:23

takasima20

総合スコア7458

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問