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

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

ただいまの
回答率

90.47%

  • JavaScript

    16982questions

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

  • 関数

    223questions

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

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

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 1,682

aaaaaaaa

score 469

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

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

+3

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

beforeHoge(); // (1) beforeHoge の定義文より前に呼び出し文が書ける

function beforeHoge() {
  hoge('定義前に呼んでもエラーにならない');
}

function hoge(msg) {
  console.log(msg);
}

beforeHoge(); // (2) もちろんここでも実行できる


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

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

beforeHoge(); // (3) ここで TypeErro 発生

var beforeHoge = function () {
  hoge('定義前に呼んでもエラーにならない');
}

function hoge(msg) {
  console.log(msg);
}

beforeHoge(); // (4) これは実行できる


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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/04/22 00: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)」を含める事ができる事でしょうか。

    キャンセル

  • 2016/04/22 06:55

    ご指摘ありがとうございます。
    こういう風に質問があって、それにあやふやでもいいから回答があって、そこにツッコミが入って、最終的に全体としてより役に立つ、より正しい情報ができあがる、というのがこういうソーシャルメディア的なもののよいところだと思っています。他の方に敬意を払えない(質問態度が悪い、検証・裏付けのさぼりなど)ことへの免罪符になっていはいけないと思いますが、質問も回答も、臆することなくでき、また、そこに臆することなくコメントできる、teratail にそういう文化が醸成されることは喜ばしいことであり、think49 さんがツッコミを入れてくださったことはそういう意味でもたいへん嬉しいです。

    ECMAScript をしっかり勉強したことはなくて、ES6 にキャッチアップするのはしんどいなあ、と思っているロートルですので、提示していただいたリンク先を全部読んでちゃんと理解して、というのはやや厳しい気がしていますが、少なくともより正しい用語を使うように努めます。あと、過去に私が「function 文」と言及している回答には、(できるかぎり)ここの think49 さんのコメントを参照するよう、追加のコメントを付けてまわろうと思います。

    キャンセル

  • 2016/04/27 08:39

    次の二つの質問でも「function 文」という用語を使ってしまっていたので、「間違った用語でした」ということを追記しておきました。

    「function()とは??」https://teratail.com/questions/32542
    「【jQuery】関数名にカッコがない呼び出し方は何?」https://teratail.com/questions/30842

    キャンセル

checkベストアンサー

+2

 変数の巻き上げ(Variable hoisting)

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

'use strict';
console.log(variableExpression);  // undefined

/**
 * 関数式(VariableStatement)
 */
var variableExpression = function variableExpression () {};

console.log(variableExpression);  // function variableExpression() {}

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

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

'use strict';
console.log(letExpression);   // ReferenceError: letExpression is not defined
console.log(constExpression); // ReferenceError: constExpression is not defined

/**
 * 関数式(LexicalDeclaration)
 */
let letExpression = function letExpression () {};
const constExpression = function constExpression () {};

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

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

'use strict';
console.log(declaration);  // function declaration () {}

/**
 * 関数宣言(FunctionDeclaration)
 */
function declaration () {}

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

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

'use strict';
console.log(blockedDeclaration); // ReferenceError: blockedDeclaration is not defined

/**
 * 関数宣言(Strict Mode ではブロックスコープ)
 */
if (true) {
  console.log(blockedDeclaration);  // function blockedDeclaration() {}
  function blockedDeclaration () {}
}

console.log(blockedDeclaration); // ReferenceError: blockedDeclaration is not defined

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

console.log(blockedDeclaration); // undefined

/**
 * 関数宣言(sloppy mode では関数スコープ)
 */
if (true) {
  console.log(blockedDeclaration);  // function blockedDeclaration() {}
  function blockedDeclaration () {}
}

console.log(blockedDeclaration);    // function blockedDeclaration() {}

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

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

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

'use strict';

if (true) {
  function blockedDeclaration () {} // SyntaxError
}

 更新履歴

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

Re: aaaaaaaa さん

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

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

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

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

0

function beforeHoge() {
  hoge('定義前に呼んでもエラーにならない');
}

function hoge(msg) {
  console.log(msg);
}

function afterHoge() {
  hoge('定義後に呼んでもエラーにならない');
}


こういうことでは?

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

関連した質問

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

  • JavaScript

    16982questions

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

  • 関数

    223questions

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