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

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

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

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

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

Q&A

3回答

3005閲覧

宣言と定義の違いについて

COCO-nuts

総合スコア13

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

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

2グッド

3クリップ

投稿2017/08/19 09:52

PHP, js, rubyでの宣言と定義の違いを教えてください!!!!
下のサイトを読んだのですが、あまり内容がわからなくて・・・

https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13120175843
https://msdn.microsoft.com/ja-jp/library/0e5kx78b.aspx

s8_chu, beicun👍を押しています

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

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

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

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

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

ockeghem

2017/08/20 02:31

なぜ宣言と定義の違いを知りたいのかと思う理由を書いたほうが、希望に沿う回答が得られやすいと思います。
guest

回答3

0

ECMAScript 2017

原則として、この回答は ECMAScript 2017 の仕様を元にしています。
ECMAScript 2017 は JavaScript の根幹となる標準仕様です。

宣言 (Declaration)

ECMAScript 2017 で「宣言 (Declaration)」と名の付く用語をリストアップします。

上記節に出てくる Syntax (文法) を日本語に翻訳します。

  • 宣言 (Declaration)
  • 巻き上げ可能な宣言 (HoistableDeclaration)
  • Class 宣言 (ClassDeclaration)
  • レキシカル宣言 (LexicalDeclaration)
  • 関数宣言 (FunctionDeclaration)
  • ジェネレータ宣言 (GeneratorDeclaration)
  • 非同期関数宣言 (AsyncFunctionDeclaration)
  • 変数宣言 (VariableDeclaration)

ここで一つの疑問が浮かびます。
宣言とは、「誰が何に向かって宣言している」のでしょうか。
この場合は「コードがパーサに向かって宣言している」といえます。
宣言はコードを構成する部品に過ぎず、中にはそれのみでは valid なコードになれないもの(例: VariableDeclaration)もあります。
パーサはあらゆる宣言を解釈して、コードを実行可能な状態にコンパイルします。

定義 (Definition)

宣言と同様、ECMAScript 2017 で「定義 (Definition)」と名の付く用語をリストアップします。

定義は宣言よりも広い意味となります。

上記タイトルを日本語に翻訳します。

  • 関数定義 (Function Definitions)
  • アロー関数定義 (Arrow Function Definitions)
  • メソッド定義 (Method Definitions)
  • ジェネレータ関数定義 (Generator Function Definitions)
  • Class 定義 (Class Definition)
  • 非同期関数定義 (Async Function Definitions)
  • 非同期アロー関数定義 (Async Arrow Function Definitions)

定義は宣言よりも総合的な意味合いが強いように読めます。
宣言という言葉は Syntax 上に出てきますが、Definition が出てくるケースはほとんどありません(ゼロではありませんが、少なくとも上にあげたものにはありません)。
詳細は後述しますが、宣言(Declaration)という構成要素をパーサが解釈(パース)し、関数や変数が定義される事を表しているのだと思います。

宣言する (declare)

ECMAScript syntax intentionally resembles Java syntax. ECMAScript syntax is relaxed to enable it to serve as an easy-to-use scripting language. For example, a variable is not required to have its type declared nor are types associated with properties, and defined functions are not required to have their declarations appear textually before calls to them.

機械翻訳「ECMAScript構文は意図的にJava構文に似ています。 ECMAScript構文は、使いやすいスクリプト言語として機能するように緩和されています。 たとえば、変数の型宣言やプロパティに関連する型の必要はなく、定義された関数の宣言を呼び出す前にテキストで表示する必要はありません。」

"定義された「関数の宣言」を呼び出す" とあります。
これは下記リンク先の Syntax で定義されている FunctionDeclaration (関数宣言) を表しており、「定義された FunctionDeclaration を呼び出す」と読み替えることが出来ます。

ここから読み取れるのは、宣言してから定義するという順番性です。
「関数宣言を定義する」とは、関数を「宣言」する事で「定義」が完了する事を表しています。
ですので、「関数定義を宣言する」のように逆の順番で表現することは出来ません。

定義する (define)

A var statement declares variables that are scoped to the running execution context's VariableEnvironment.

機械翻訳「var 文(statement)は、実行中の実行コンテキストのVariableEnvironmentにスコープされている変数を宣言します(declares)。」

これは VariableStatement という変数文を解釈⇒実行する過程の一文です。
変数文は Syntax 上の VariableDeclaration (変数宣言)を解釈します。

JavaScript

1var a, b; // 変数文全体で VariableStatement を表す。a, b がそれぞれ VariableDeclaration を表し、複数の変数宣言を解釈できる。

Within the scope of any VariableEnvironment a common BindingIdentifier may appear in more than one VariableDeclaration but those declarations collective define only one variable.

機械翻訳「VariableEnvironmentのスコープ内では、共通のBindingIdentifierが複数のVariableDeclarationに現れることがありますが、それらの宣言は1つの変数のみを定義します。」

細かな説明は省きますが、重要なのは「宣言を解釈して定義する」という順番性です。

JavaScript

1var a = 1, b = 2;

a = 1 という変数 a の宣言」と「b = 2 という変数 b の宣言」を解釈し、VariableStatement として認められる事で 変数 a, b が定義される、となります。

JavaScript

1var a = 1, b = !!!; // SyntaxError: Unexpected token ;

このコードは変数 a を宣言しましたが、変数 b の宣言に失敗している為、結果として変数 a, b定義されていません

ユーザ定義関数(User-defined function)

ユーザ定義関数(User-defined function) はECMAScript 2017 に存在しない用語ですが、比較的読む見る用語の為、触れておきます。
下記の関数 foo のようなコード制作者が定義した任意の関数を「ユーザ定義関数」と呼びます。

JavaScript

1function foo () { 2 console.log(foo); 3}

コード制作者は上記コードを「関数 foo を定義する」と表現します。
関数宣言(FunctionDeclaration)は関数を定義する上で最上位の Syntax なので、「関数 foo を宣言する」と表現しても概ね通じますが、最終的に関数 foo が実体化された事を強調するには「定義する」の方が好ましいといえます。

また、「ユーザ定義関数(User-defined function)」という言葉はありますが、「ユーザ宣言関数(user-declared function)」という言葉は読んだ覚えがありません。
これも宣言してから定義するという順番性を表しているのかもしれません。

関数宣言(FunctionDeclaration)と関数式(FunctionExpression)

上記リンク先では、大別して次の2つの Syntax が定義されています。

  • 関数宣言 (FunctionDeclaration)
  • 関数式 (FunctionExpression)

関数定義は関数宣言と関数式を総合した名称です。
従って、「関数定義 === 関数宣言」ではありませんし、関数宣言と関数式は別個の存在として定義されています。

JavaScript

1function foo () { console.log('foo'); }

上記コードは関数宣言(FunctionDeclaration)を定義しています。

JavaScript

1(function bar () { 2 console.log('bar'); 3}());

上記コードは関数式(FunctionExpression)を定義しています。

JavaScript

1var piyo = function piyo () { 2 console.log('piyo'); 3};

上記コードは関数式を定義した後に変数 piyo を定義しています。

「変数文」と「関数式」の定義が独立している点に注意して下さい。
厳密には、変数文の処理過程で変数宣言が行われている事になります(詳細は「定義する」の節を参照して下さい)。

  1. 関数式 piyo を定義する
  2. 変数 piyo を宣言する
  3. 変数 piyo を定義する

更新履歴

  • 2017/08/21 11:41 「関数宣言(FunctionDeclaration)と関数定義(Function Definitions)」の節を追記
  • 2017/08/25 12:38 見出しを修正。関数宣言(FunctionDeclaration)と関数定義(Function Definitions) -> 関数宣言(FunctionDeclaration)と関数式(FunctionExpression)

Re: COCO-nuts さん

投稿2017/08/20 02:52

編集2017/08/25 03:39
think49

総合スコア18170

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

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

think49

2017/08/20 03:49

FunctionDeclaration と FunctionExpression の違いに触れるのを忘れていました。 後で追記します。
guest

0

宣言(declaration)と定義(definition)という言葉について何を意味するのかは言語によっては特殊な意味を持つも事があります。ですが、ほとんどの場合はC言語での意味とほぼ同じになるでしょうから、C言語での宣言と定義が意味するところが、各言語においてどうなるかを説明していきます。

####C言語での宣言と定義

C言語は宣言と定義を分けて書くことができる言語です。分けて書くことができない言語も存在しますし、C言語であっても宣言と定義が兼ねる場合があります。この点はご注意ください。

宣言は「ある識別子(identifier)はこういう類いの物である」と宣言することです。識別子というのは変数名とか関数名とか型名とかの事です。プログラムの中でaという識別子を使うとき、

C

1int a(int);

と書いてあったとします。これは関数の宣言であり、「aはint一つを引数にしてintを返す関数である」ということを宣言します。この時点ではどのような関数であるかはわかりません。しかし、関数であることはわかっているので、この後のコードではa(42)と言った形でaを関数として使用することができます。同じように、これはintの変数だと言った宣言が可能です。

対して、定義は「ある識別子(identifier)は具体的にこういう中身である」と定義することです。先ほどのaを定義してみましょう。

C

1int a(int x) 2{ 3 return x + 1; 4}

宣言だけではaは関数であるということしかわかりませんでした。しかし、定義によってどんな動作をする関数であるかと言うことが定義されます。上の例では引数に1足した数を返す関数という定義です。コードの中でa(42)等と書かれた場合は、この定義に従って関数の評価が行われ、43を返す事でしょう。

注意して欲しいのは、定義は宣言も兼ねられると言うことです。最初の宣言を書かずに二番目の定義だけを書いたら、定義の部分で宣言がされたと見なされます。宣言と同じように、この後のコードでaを使うことが可能です。

逆に宣言と定義を分離できない場合もあります。例えば、型を定義するtypedefは宣言だけを行うことはできません。Tは型ですと宣言すると同時に、具体的に○○と言う型ですと定義する必要があります。

なお、変数の定義についてですが、変数はローカル変数なのかグローバル変数なのかといった書き方によって宣言が定義を兼ねる場合もあれば、別々の場合もあり、複雑なので具体的には言及しません。ただ、変数の場合はメモリ上に確保されるところをもって定義としているようです。

以上がC言語の場合ですが、これとほぼ同じなのはC++ぐらいです。他の言語では宣言と定義がわかれていない場合があります。

####PHPでの宣言と定義

PHPについては、細かい仕様を語れるほど詳しくないので、他の人に説明を任せます。ごめんなさい。

####ECMAScript(JavaScript)での宣言と定義

ECMAScriptの関数もクラスも変数も宣言と定義を兼ねます。先行して宣言だけを行うことはできません。

JavaScript

1function a(x) { 2 return x + 1; 3}

このコードを定義の部分を外して書くことができないと言うことです。

人によっては次のコードは宣言と定義がわかれていると言うかも知れません。

JavaScript

1var a; 2a = function (x) { 3 return x + 1; 4};

このコードの正しい解釈は、aという変数が定義され(この時点ではaにはundefinedが入っています)、その後にaという変数に関数が代入されて、aは関数として使用できるようになったと言うことに過ぎません。aが先行して宣言されたわけではないのです。

なお、仕様上は、章の題名には「Function Definitions(関数定義)」という言葉を使いながら、文法(syntax)では「FunctionDeclaration(関数宣言)」という言葉を使っています。仕様上の文法では関数宣言という名前ですが、実際は具体的な中身が必ず存在するため、最初に述べたC言語での意味での定義がされていると言って差し支えありありません。**これは、ECMAScriptの仕様書上の用語として「宣言」と「定義」がどうなっているとかはまた別の話であり、決して混同しないでください。**もし、混乱してしまったのであれば、私の書き方が悪かったのだと思われますので、文章力に不足があり、申し訳ありません。仕様書の「宣言」と「定義」について知りたい場合は、think49さんの回答が参考になりますから、そちらを読んでください。この回答をいくら読んでも、仕様上の意味での解釈については一切助けにはなりません。

では、ECMAScriptには定義が無い宣言が無いのかというとそうではありません。importとexportがあります。importではこの外部ファイルをインポートしますという宣言だけです。具体的な中身は外部ファイルに書いてあり、importで定義しているわけではありません。exportでは具体的な中身を書くこともできますが、名前だけ指定してexportすることも可能です。つまり、この変数や関数はエクスポートしますと宣言するだけで、その中身は別の所に書いてあると言うことができます。

####Rubyでの宣言と定義

Rubyも宣言と定義を分けて書くことはできず、全てが宣言と定義を兼ねます。

Ruby

1def a(x) 2 x + 1 3end

aはメソッドとして定義されましたが、メソッドであることを前もって宣言するような書き方はありません。必ず、具体的な中身(何もしないという空の場合もあり得る)が定義される必要があります。

クラスについては次のようにできるから、分けて書けると指摘する人もいるかも知れません。

Ruby

1A = Class.new 2class A 3 def initialize(x) 4 @x = x 5 end 6 def plus_one 7 @x + 1 8 end 9end

最初にクラスAについては何も中身が無いClassオブジェクトとして作成しました。これは宣言と言えるのでしょうか?いいえ、言えません。具体的にClassのオブジェクトとして生成しているからです。Rubyはオープンクラスと言いわれる後からクラスの中身を実装できる仕組みであるため、後から定義されると言うより、定義が追加で変わっていくと言うだけに過ぎません。最初が定義を意味しないわけではありません。


動的な言語(プログラムの途中で、識別子の意味が動的に変わっていく言語、ECMAScriptとかRubyとか)においては、宣言と定義は一緒の場合が多いように思えます。でも、静的な言語(コンパイル時に、識別子の意味が静的に決定される言語、JavaとかC#とか)であっても、最近の言語は一緒の場合が多いように思えます。宣言と定義の分離は、マシンの性能もコンパイラの品質も貧弱な時代に、静的な言語でコンパイルするための助けになるという意味では有用だったのかも知れませんが、現在においては、単に面倒なだけとされて、廃れた手法になっていっているのかも知れません。


最後に、上では関数の宣言と定義だけで、変数については、少しぼかした表現で、詳しく書いていません。C言語上では、その変数の実体が作られるところ(メモリ領域が確保されるところ)が定義になるのですが、細かく言うとさらに倍の内容になりますので、省いています。PHPのglobalキーワードが変数で宣言と定義がわかれている例になるのですが、PHPについては全てを語るほど詳しくないと言うこともあり、触れていませんでした。

また、もう一つぼかして書いていることで「関数が定義される」と「作成された関数が入っている変数が定義される」の(動作の違いでは無く)意味的な違いを詳しく解説していません。申し訳ありませんが、そこまで話をしてしまうと、どんどん話がずれて言ってしまうので、避けてしまいました。どこかで機会があれば、網羅的に宣言と定義について、記事を書きたいとは思いますが、ここでの回答はここまでとさせていただきます。

投稿2017/08/19 11:19

編集2017/08/25 10:48
raccy

総合スコア21735

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

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

think49

2017/08/21 02:45 編集

> なお、仕様上は、章の題名には「Function Definitions(関数定義)」という言葉を使いながら、文法(syntax)では「FunctionDeclaration(関数宣言)」という言葉を使っています。そのため、文法では関数宣言という名前ですが、実際は具体的な中身が必ず存在するため、定義といって差し支えありありません。 仕様上は「関数宣言を定義する」という記述がありますし、関数式と関数宣言は独立している為、「関数宣言 === 関数定義」ではないと思うのですが、いかがでしょうか。
raccy

2017/08/21 09:43 編集

think49さん すいません、私自身少し混乱していました。上の話はECMAScriptの仕様書上の用語としての宣言や定義ではなく、C言語での意味での宣言や定義がECMAScriptではどのようになっているかという話です。仕様書上の名称では宣言と使われているけれどもという注意事項としてかこうとしたのですが、意味がちょっと通じない文章になっていました。申し訳ありません。 文章を修正しましたので、ご確認ください。
think49

2017/08/22 16:24

> C言語での意味での宣言や定義がECMAScriptではどのようになっているかという話です。 その場合、「ECMAScript(JavaScript)での宣言と定義」の見出しが適切ではないように感じました。 「C言語流に解釈したJavaScriptでの宣言と定義」と書かれているとしっくりくると思いましたが、いかがでしょうか。 「ECMAScript」と書かれていますと、仕様上の定義を連想してしまいます。
raccy

2017/08/22 22:04

think49さん 最初に「C言語での宣言と定義が意味するところが」って書いていたんですけど、どうやらわかりにくかったみたいで、申し訳ありません。強調しておきました。仕様の話ではありません。
think49

2017/08/25 03:30 編集

遅くなりましたが、改めて何度か読み直しました。 出来るだけ解釈できるように努めましたが、まだECMAScript(JavaScript)の説明に違和感が残っているように感じられました。 - 仕様の説明ではないにも関わらず、ECMAScript 仕様の Syntax を参照しています(文脈的に「宣言」と「定義」が同義であると説明する為の根拠として用いられているようですが、仕様上では「宣言」と「定義」は別物として扱われています) - 関数宣言(FunctionDeclaration) には触れられていますが、関数式(FunctionExpression)及び「変数宣言(VariableDeclaration)」に触れられていません 特に変数宣言に触れていないのが致命的で、変数宣言があるだけで解釈に大きな違いが出てくると思います。 私は次のように解釈しました(ECMAScript 2017準拠)。 https://jsfiddle.net/5c9vgey9/ このコードには関数宣言(FunctionDeclaration)がありません。 ですので、関数宣言(FunctionDeclaration)だけを元に説明するのは無理があります。 > 動的な言語(プログラムの途中で、識別子の意味が動的に変わっていく言語、ECMAScriptとかRubyとか)においては、宣言と定義は一緒の場合が多いように思えます。 私としては、C言語とECMAScriptの「宣言」と「定義」が同じようには感じられませんでした。 他人に説明する際には「C言語における型宣言」のように前置きしないと誤解を生むのではないかと思いました。
raccy

2017/08/25 11:02 編集

下手に仕様書の話を持ち出してしまったのが悪かったようで申し訳ありません。仕様書での意味ではないということ、それと混同しないようにすることを強調しておきました。 変数の定義について書いていないのはわざとです。私としては`var a;`と書いただけで、C言語で意味するところの「宣言」かつ「定義」になると解釈しています(ECMAScript仕様上での「定義」を意味していると言っているのでは決してありません)。最後に言い訳を追加していますが、全て書くと長くなって、書くのがつらいので、ここでは勘弁して欲しいところです。ごめんなさい。 私もC言語とECMAScriptで用語が全く同じだと思っていませんし、そう主張したいわけではありません。ただ、質問が複数の言語に渡ってどうなっているのか、参考にしているURLがCおよびC++であったことから、C言語での意味で、それぞれの言語がどうなっているのかを解説したのが今回の回答です。質問者が、各言語の使用上の意味での回答が知りたかったのか、C言語においての「宣言」や「定義」が各言語ではどうなっているのかを知りたかったのか、どちらを聞きたいのか一瞬悩みましたが、言語が複数であることとURLから、後者であると判断しました。 もしかしたら、think49さんの回答のように、ECMAScript仕様書上での「宣言」「定義」を質問者が求めていたのかも知れませんが、そうであれば、私の回答は質問者の役には立たなかっただけかと思っています。
guest

0

まず1つ言えば、言語によって対応する言葉が違ってきます

C言語では(MSDNを見ての通り定義でない宣言があるので)「宣言」と「定義」を峻別する必要が生じますが、ここで上げた3つの言語は、「中身のない関数の宣言だけ」とか「他のファイルで定義されたものを参照するだけの宣言」が存在しないので、変数や型について「定義」や「宣言」という言葉を区別する必要がありません

ただし、JavaScriptでの'use strict';やPHPのdeclareなどは、プログラム内に現れる変数や型と関連を持たずに動作を変えるものですので、「宣言」と呼ばれます。

投稿2017/08/19 10:55

maisumakun

総合スコア145208

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問