javascriptは、ほかの言語と違い関数内に宣言された局所変数は、関数内全体で有効なので宣言前でもundefindになりますが呼び出せます。ただ、解かりやすくするため、関数の最上部で宣言しますが
javascript以外は、その変数を利用するときに宣言するようです。これを変数の巻き上げといいますが、とあるサイトに「関数の巻き上げ」なる用語を使用しているサイトを見つけました。
書籍やネットを探っても、変数の巻き上げ以外に巻き上がるものは記述されておりませんでした。
そのサイトの文章を見てもいまいちなにを言っているのか分かりません。関数の巻き上げとはいったい何なのでしょうか。
http://d.hatena.ne.jp/kousukekayo/20090827/1251363441
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答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) のところでは、「変数の巻き上げ」によって、beforeHoge
は undefined
ではありますが、変数としては存在しています。しかし、undefined
は関数オブジェクトではないので ()
をつけて実行しようとすると、「beforeHoge is not a function」とかの TypeError になります。で、(3) をコメントアウトしてみると、(4) はエラーなく実行されます。
念のため繰り返しますが、function
文で関数を定義した場合には、(1) のように、その定義文の前に実行できる、すなわち、beforeHoge
という名前で関数オブジェクトにアクセスできる、というのが「関数の巻き上げ」です。
投稿2016/04/21 13:09
総合スコア2468
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- で未対応です)。
- 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) – ECMA-262 6th Edition
- block-level function declaration - ECMAScript 6 compatibility table
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)」まではブロックレベル関数宣言の利用を控えた方がいいかもしれません。
- Where's Walden? » New ES5 strict mode requirement: function statements not at top level of a program or function are prohibited
- Windows デスクトップ製品のライフサイクル
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総合スコア18189
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
「関数の巻き上げ」とは、スコープに関することで、
と説明されているようですが?
投稿2016/04/21 12:23
総合スコア7460
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/04/21 15:37
2016/04/21 21:55
2016/04/26 23:39