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

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

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

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

Q&A

解決済

5回答

1495閲覧

Java Script なぜこのコードが動くのかが分からない

divclass123

総合スコア35

JavaScript

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

0グッド

1クリップ

投稿2021/07/15 18:11

編集2021/07/15 18:12
var a ={}; a.abc = test; // aオブジェクトのプロパティabcに関数testを代入 a.abc(); //なぜ、testメソッドをこの行の上で定義してないのに // 動く? // ここで定義したメソッドを呼び出してるんじゃないの? // オブジェクトにくっついてる関数をメソッドと言う function test(){ alert("test") }

質問詳細

jsは上から読んでいってるので、

function test(){
alert("test")
}

でメソッド定義しても

定義したメソッドの上でメソッドを呼び出してるから
undifined method errorとかになりそうですが、
なぜか動きます。

その後a.abcにtestを代入しています。これは、当然aのプロパティabcです。testは関数であり、つまりオブジェクトでしたから、同じ関数がa.abcに代入されます

後このようにサイトには書いてあるのですが、
testが関数なら
a.abc = test();
と代入する方がなんだかしっくりくるのですが、
なぜそのように書かないのでしょうか?

ちなみにこのように書いても動きました。

なぜ動くのか教えていただければ幸いです。
よろしくお願いいたします。

参照

https://uhyohyo.net/javascript/1_4.html

メソッド
次に、メソッドというものを解説します。そんなに難しいものではなく、プロパティのうち、関数であるもののことをメソッドといいます。つまり、プロパティの一種です。

var a = {};
a.abc = test;
a.abc();

function test(){
alert("test");
}
やっていることは難しくありません。1行目でaに{}を代入していますが、これは「プロパティを1つも持たないオブジェクト」です。「プロパティ名 : 値」の組が1つもないわけですね。

そして、その後a.abcにtestを代入しています。これは、当然aのプロパティabcです。testは関数であり、つまりオブジェクトでしたから、同じ関数がa.abcに代入されます。つまり、a.abcを呼び出すのはtestを呼び出すのと同じです。(詳しい方は、厳密には少し違うということをご存知だと思いますが、それはここでは解説しません。)

なので、次の行ではそれを呼び出しています。ちゃんと"test"と表示されるのが分かります。

もともとメソッドの本当の意味はこんなところには無いのですが、それは今回は解説しません。オブジェクトにくっついてる関数をメソッドと呼ぶということは覚えておきましょう。

ちなみにこのように、関数定義は、使う場所より後ろに書いてあっても機能します。

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

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

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

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

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

guest

回答5

0

ベストアンサー

投稿2021/07/15 18:17

gentaro

総合スコア8947

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

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

divclass123

2021/07/16 05:50

ありがとうございます >コード内で関数を書く前に、関数呼び出しを最初に書いても、コードは動作します。これは JavaScript でコンテキスト実行が動作するためです。 これが答えなのですかね、、、。 コンテキスト実行はjsのコードを実行可能にすることを指すと書いてありました。(後からこの質問を見る人用) jsが賢いから、場合によっては巻き上げ(上から順番にコードを読み込んでいくわけではない)をするってことでしょうか?
divclass123

2021/07/16 05:53

jsが賢いってことをもっと言うと 関数宣言(メソッド呼び出し)をjsが覚えていてくれて(メモリーに一時保存) るから巻き上げが可能と言う認識で大丈夫でしょうか?
gentaro

2021/07/16 06:08

賢いとか云々じゃなく、そういう「言語仕様」に従って言語ができてるんだから可能だというシンプルな話。 その言語を実行するランタイムがどのように実装されているのかをプログラマが意識する必要はない。
guest

0

C言語やC++と絡めて学ぶと理解しやすいかも。

オブジェクトが持つメソッドや関数(function)は、C言語でいう関数ポインタのようなものでしょうか。

JavaScript

1a.abc = test;

とすると、aが持つメソッド abc (この時点ではメソッドなのかプロパティなのか判別できませんが)
のアドレス先を test関数のアドレスにする。

そうすると、aが持つabc == test関数 という図式になる。

そのため、関数と同じような動きをすることが可能です。

ちなみに、

JavaScript

1a.abc = test();

とすると、test関数の戻り値をa.abcに入れているということになります。


JavaScriptは使うだけなら強い言語ですが、この言語だけで理解しようとするには厳しいです。

投稿2021/07/16 03:18

編集2021/07/16 03:20
BeatStar

総合スコア4962

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

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

divclass123

2021/07/16 07:11

Cは触ったことないのでわからなかったのですが、理解が難しいのですね、、、。 御回答頂きありがとうございます。。。
guest

0

https://qiita.com/divclass123/items/65df87968b3b8973cb1e

https://qiita.com/divclass123/items/76a6f89e063cc939986f

皆様の知見を抽出して自分なりの解決方法を書いてみましたが、
なぜ巻き上げ機能があるのかがいまいち理解できてないんで
これから学習していって、未来の自分が理解してくれることを期待します。

投稿2021/07/16 16:49

divclass123

総合スコア35

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

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

maisumakun

2021/07/16 22:19 編集

> なぜ巻き上げ機能があるのかがいまいち理解できてないんで そこは所与のものなので、理解しようとしても仕方がないかと思います。
divclass123

2021/07/17 05:38

まぁ確かに特に初学者にとっては理解しがたいですね。。。。 巻き上げ機能のメリットって何かあったりするんですか?
maisumakun

2021/07/17 06:02

おそらくは歴史的な経緯(規格もなかった時代に各ブラウザが適当に作ったものを、つじつまを合わせるために規格自体に歪みが入ってしまった)かと思います。 A→B→C→Aのように複数の関数を循環して呼ぶ構造(これ自体は、アルゴリズムによっては便利です)を取るのでもない限り、巻き上げは積極的に使うものではありません。
guest

0

同じスコープ内でfunctionで宣言した関数は先に評価されます
無名関数などで設定された関数は呼び出しより前に宣言する必要があります

javascript

1var a ={}; 2a.abc = test; //エラー 3a.abc(); 4test=function(){alert("test1");}

上位スコープから持ち込まれた関数はメソッドを設定するタイミングで
結果が変わってきます

javascript

1function test(){alert("test1")}; 2{ 3 var a={}; 4 a.abc = test; 5 test=()=>alert("test2"); 6 a.abc(); // test1 7 a.abc = test; 8 a.abc(); // test2 9}

投稿2021/07/16 00:24

yambejp

総合スコア116724

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

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

divclass123

2021/07/16 07:29

確かに無名関数だと、先に関数呼び出してもうまく動作しないですね、、、。 関数の違いをもう少し勉強していきたいと思います。 ありがとうございます。
divclass123

2021/07/16 16:39 編集

function test(){alert("test1")}; { var a={}; a.abc = test; test=()=>alert("test2"); a.abc(); // test1 a.abc = test; a.abc(); // test2 } これがいまいちなぜそのような実行結果になるか分からなかったのですが、 今理解できたきがします。。。
divclass123

2021/07/16 16:43

>上位スコープから持ち込まれた関数はメソッドを設定するタイミングで 結果が変わってきます と言うのは、 a.abc = test; このタイミングですよね、、、、!? なんかやっと理解できた感じで嬉しいです!
guest

0

testが関数なら

a.abc = test();
と代入する方がなんだかしっくりくるのですが、

これは、a.abc = test意味が違いますtest()の実行結果を代入する、ということになります。

投稿2021/07/15 22:38

maisumakun

総合スコア146018

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

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

divclass123

2021/07/16 05:59

ありがとうございます。勉強になりました。 a.abc = test はどう言った意味なのでしょうか? メソッドの名前だけをとりあえず定義してるような状態で、 後からそのメソッドが何を実行するかを function testで定義してると言った感じでしょうか?
maisumakun

2021/07/16 06:14 編集

違います。 JavaScriptでは、関数も変数に代入したりできるオブジェクトです。a.abc = testは「testに入っている(関数オブジェクトという)値をa.abcに代入する」という意味です。巻き上げですでにtestには値が割り振られています。
divclass123

2021/07/16 06:42

ありがとうございます! a.abc = testは式を代入している a.abc = test();は式の計算結果を代入していると言う違いなのですね! 理解できました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問