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

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

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

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

PHP

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

JavaScript

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

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

Q&A

解決済

1回答

2151閲覧

laravel、 jsファイルで、読み込んだスクリプトの関数が実行できない。

Patao_program

総合スコア22

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

PHP

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

JavaScript

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

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

0グッド

0クリップ

投稿2021/09/09 02:28

前提・実現したいこと

jsファイルで関数を作って,htmlのonclickから発火させたい。

発生している問題・エラーメッセージ

scriptタグ直で書いた関数(test)は実行できるが、jsファイル由来の関数(test)は実行されずReferenceErrorとなってしまう。

1:170 Uncaught ReferenceError: test is not defined

該当のソースコード

php

1<x-app-layout> 2 <div class="py-12"> 3 <div class="max-w-7xl mx-auto sm:px-6 lg:px-8"> 4 <div class="max-w-5xl w-full mx-auto bg-white overflow-hidden shadow-sm sm:rounded-lg"> 5 <div class="p-6 mx-auto bg-white border-b border-gray-200 text-center"> 6 <h1 class="text-4xl mb-4">{{ $group->title }}</h1> 7 <p class="mb-8">製作者: {{ $group->username }}</p> 8 <p class="mb-8">問題数: {{ $count }}</p> 9 <div class="relative max-w-md mx-auto"> 10 <label style="left: 10.5rem" class="py-1 px-2 -top-4 bg-white absolute" for="info"> 11 クイズの概要 12 </label> 13 <p class="w-full py-4 px-4 mb-8 border border-yellow-500" id="info" class="mb-8"> 14 {{ $group->information }}</p> 15 <label for="good-count"> 16 いいね 17 </label> 18 <p id="good-count" class="mb-8 mt-2"><span data-control="0" onclick="test()" 19 class="fas fa-heart mr-3 cursor-pointer"></span>{{ $group->good_count }}</p> 20 <div class="flex flex-col"> 21 <button data-control="1" class="mb-8 border border-sky-400 py-2 px-4">お気に入りに追加</button> 22 <button 23 class="py-2 px-4 text-white border border-red-400 bg-red-400 focus:border-red-500 focus:bg-red-500 animate-pulse">クイズを解く</button> 24 </div> 25 </div> 26 </div> 27 28 </div> 29 </div> 30 </div> 31 <script src="{{ asset('js/like.js') }}"></script> 32 <script> 33 // test(); 34 // function test() { 35 // console.log('test'); 36 // } 37 </script> 38</x-app-layout> 39

javascript

1function test() { 2 console.log('test'); 3} 4 5// test();

試したこと

laravelMixで新たなエントリーポイントを作り(like.js)それを、scriptで読み込ませています。
like.js自体は、200でしっかりと読み込まれています。
npm run dev でコンパイルしてます。

like.js内で、test()を実行したところ、testとコンソールに表示されました。しかしhtmlからは上手く実行できないのが謎です。

また js/like.jsで読み込んだ後のスクリプトでも、test()の実行を試みましたが、同じエラーが起きました。グローバルスコープであるはずなのになぜでしょうか?

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

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

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

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

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

guest

回答1

0

ベストアンサー

JSの変数スコープの勉強が必要になるでしょう

参考記事: 関数とスコープ - JavaScript Primer

js

1function test () { 2 console.log(123); 3} 4test(); // これは実行出来るが

js

1// 関数を定義してその中で関数や変数を定義しても 2(function(){ 3 function test () { 4 console.log(123); 5 } 6})(); 7 8// test関数は他の箇所のスコープにあるので使えない 9test(); // Uncaught ReferenceError: test is not defined

JavaScriptは関数を定義する度にスコープが作られます。

JavaScriptは指定した名前の変数・関数が今のスコープに無ければ
「親のスコープ」に確認しに行きます。
兄弟や子孫は探しに行きません。

js

1function test2 () { 2 console.log(234); 3} 4 5(function(){ 6 // 関数スコープを切ってtest関数を定義 7 function test () { 8 console.log(123); 9 } 10})(); 11 12(function(){ 13 // これは兄弟スコープになるのでアウト 14 // 親→祖父といった風に上にしか辿れない 15 test(); 16 17 // こちらは親スコープに関数が存在しているのでセーフ 18 test2(); 19})();

laravelMixで新たなエントリーポイントを作り(like.js)それを、scriptで読み込ませています。

ブラウザに搭載されたデベロッパーツールのNetworkタブを開いて
一度リロードしてlike.jsファイルに具体的にどんなコードが書き込まれているかを確認してみてください。

恐らくですが、ファイルの全体を大きく関数で包んでいるはずです。
そしてスコープを作ってからその中で処理を記述しているはずです。

こういう関数で包んでスコープ作る作戦をクロージャーと呼びます。

投稿2021/09/09 10:28

編集2021/09/09 10:29
miyabi-sun

総合スコア21203

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

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

Patao_program

2021/09/09 22:43

本当ですね!バンドルされるとラッピングされてしまうのですね。 グローバルとして作用してほしかったので、like.jsを読み込む前に、変数を宣言して関数を代入するという対処をするしかない感じですかねー
miyabi-sun

2021/09/14 06:35

最近PHPには疎いのでLaravelには詳しくないですが、 Laravel MixではWebpackを使っているようです。 Webpackは Node.jsが利用しているrequireを再現したJSファイルにコンパイルして メインロジックとともに書き出すという手法です。 JavaScriptに直書きした場合、 グローバルスコープに値を保存したければ `window.state = 123;`という風にwindowオブジェクトがほぼグローバルスコープになっているので windowオプジェクトにぶら下げるコードを記述してやれば動くかと思います。 でもまぁ、Node.js流儀の方が綺麗なコードになるので Webpackを覚えてそれに準拠した形で利用することを推奨します。
Patao_program

2021/09/18 07:21

> Node.js流儀の方が綺麗なコードになる これは、どういうことですか?
miyabi-sun

2021/09/18 08:56

整理整頓の話です。 大昔はC言語やPHPでグローバルスコープにとりあえず関数や変数を置いておいて…… みたいな事をやる人が多かったのですが、 システムの規模が大きくなるにつれ、相互上書き等で動作しないとかバグが大量に出るという問題に悩まされていました。 それを解決する為に 「お前ら外部のファイルに書いてある関数を利用したければ、ソースコードの上の方に提供元を書くような設計にしろ」 こういうプログラミングのテクニックというものが出来て、 一般常識みたいになっています。 なのでグローバル変数スコープは出来るだけ利用しないようにしましょう。 しかしJavaScriptには外部のライブラリを読み込む概念がありません。 scriptタグを跨いで宣言した場合、グローバルスコープ(window.変数名)に変数を定義して決め打ちで利用する必要があります。 上記の通り、宣言したと思った関数が無いとか、違うモノを参照している等中々バグを解消出来ません。 PHPやC言語で培ってきたテクニックが通用しないのです。 とりあえずJavaScriptでは暫定措置として現場レベルでは関数で括って、 外のグローバルスコープを汚さないようにしましょうねというのが暗黙の了解になりました。 SassのuseやNode.jsのrequireはグローバルスコープを汚さない為 何のライブラリの何を利用するかをソースコードの上の方に記述して そこから引っ張るような仕組みになっています。 Webpack越しにNode.js→JavaScriptを生成する時は requireをふんだんに使えるので、Node.js流儀に従うのがコードが綺麗になります。 恐らくその目的でLaravelはNode.js(Webpack)を採用しているのでしょう。 嫌なら素のJavaScriptで管理して、Laravelが用意しているJSサポート機能は削って使う方が良いと思います。
Patao_program

2021/09/18 11:41

そもそも、requireでモジュール化して汚染を防いできれいにという以前に、htmlに関数を埋め込んでも、webpackによる関数のスコープに阻まれているため、跨がらせざるおえないと思うですが、もしくは、webpackの設定をいじれば、バンドルをして出力するファイルは関数スコープで囲ませないようなことはできるのですか?
Patao_program

2021/09/18 11:42

上記では表されてないのですが、phpからデータを渡すような実装も加えています。
hentaiman

2021/09/18 12:09

> 、htmlに関数を埋め込んでも、webpackによる関数のスコープに阻まれているため、 なのでエントリーポイントとなる変数をexportとしてbootstrapまたはそれに相当するファイルでwindowオブジェクトにexportした変数を持たせて使います
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問