20210504のJavaScriptに関する記事は30件です。

繰り返し処理 while/for

while文 記述としては「while(条件式){処理}」のように記述し、条件式がTrueの間、{}内の処理を繰り返すことができます。 例 let number = 1; while (number <= 10) { console.log(number); number += 1; //number++と記述することもできる } //;(セミコロン)は必要ありません 出力結果 1 2 ︙ 9 10 上記のように記述することで、1〜10の数字を出力することができました。 number += 1;を記述しないと、変数numberは永遠に1であるため、永遠に繰り返し処理が続いてしまいます。これを無限ループと呼び、無限ループになってしまうとコンピュータに異常な負荷をかけてしまうため注意が必要になります。 for文 繰り返し処理を行う方法として、while文の他にfor文があります。 記述としては「for (変数の定義;条件式;変数の更新){処理}」のように記述することでwhile文同様に条件式がTrueの間、{}内の処理を繰り返すことができます。 例 for (let number = 1; number <= 10; number += 1){ console.log(number); } 出力結果 1 2 ︙ 9 10 上記のように記述することで、while文同様に繰り返し処理を行うことができます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[HTML/JavaScript]RPA(UiPath)でスクレイピングするためのテストページを作ってみた

[0]はじめに Zitanです。 RPAでWebスクレイピングする際のテスト用のWebページを作成することにしました。 サイト様にもよりますが、Webスクレイピング禁止にしているところもあるようで。。。 今後使うかどうかは別として、コードを残すことにしました。 [1]GitHub Pagesを使う 筆者はGithub初心者なので詳しくないのですが、、、 ここに残したのでZipファイルでダウンロードできます。 作ったサイトを見るには。。。 下の方に「GitHub Pages」がありますので、クリック。 このURLをコピペすれば誰でもアクセスできます。自由に使って下さい。※UI変更する可能性はありますが。。 静的なページであれば作成できるらしいです。今回は、HTMLとjavaScripのみを使っています。 アクセスするとログインページに遷移します。 UserName:testuser Password:password です。ただのテスト用のサイトなのでセキュリティとか気にしていません。 [1-1]ログインページ [1-2]ログイン成功 [1-3]ログイン失敗 コードは全部同じ階層です。 [2]HTMLコード [2-1]ログインページ:index.html index.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="process.js"></script> <title>Login Test Page</title> </head> <body> <center> <h1>Login Test Page</h1> <form name="login_form" action="clickButton();"> <p>Please Input your ID/Password(testuser/password)</p> <input type="id" name="id" placeholder="UserName"> <br> <input type="password" name="password" placeholder="Password"> <br> <button type="button" onClick="clickButton();">Login</button> </form> </center> </body> </html> [2-2]ログイン成功ページ:success.html success.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="process.js"></script> <title>Success Page</title> </head> <body> <center> <h1>Success Page</h1> <p>This is Success Page !</p> <dl> <dt>RPAのクラス_総務省HPより(https://www.soumu.go.jp/menu_news/s-news/02tsushin02_04000043.html)</dt> <dd> <table class="tableList" border="1"> <thead> <tr> <th scope="col" style="width: 25%;">クラス</th> <th scope="col" style="width: 20%;">主な業務範囲</th> <th scope="col">具体的な作業範囲や利用技術</th> </tr> </thead> <tbody> <tr> <th scope="row">クラス1<br />RPA(<span xml:lang="en" lang="en">Robotic Process Automation</span>)</th> <td>定型業務の自動化</td> <td> <ul class="normal"> <li>情報取得や入力作業、検証作業などの定型的な作業</li> </ul> </td> </tr> <tr> <th scope="row">クラス2<br />EPA(<span xml:lang="en" lang="en">Enhanced Process Automation</span>)</th> <td>一部非定型業務の自動化</td> <td> <ul class="normal"> <li>RPAとAIの技術を用いることにより非定型作業の自動化</li> <li>自然言語解析、画像解析、音声解析、マシーンラーニングの技術の搭載</li> <li>非構造化データの読み取りや、知識ベースの活用も可能</li> </ul> </td> </tr> <tr> <th scope="row">クラス3<br />CA(<span xml:lang="en" lang="en">Cognitive Automation</span>)</th> <td>高度な自律化</td> <td> <ul class="normal"> <li>プロセスの分析や改善、意思決定までを自ら自動化するとともに、意思決定</li> <li>ディープラーニングや自然言語処理</li> </ul> </td> </tr> </tbody> </table> </dd> </dl> </center> </body> </html> [2-3]ログイン失敗ページ:failure.html failure.html <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="process.js"></script> <title>Failure Page</title> </head> <body> <center> <h1>Failure Page</h1> <p>This is Failure Page !</p> </center> </body> </html> [3]javaScriptコード [3-1]ログインページ:prcess.js prcess.js function clickButton() { input_id = document.login_form.id.value; input_pwd = document.login_form.password.value; if(input_id == "testuser" && input_pwd == "password"){ location.href = "success.html"; return; } location.href = "failure.html"; } UserName(input_id)とPassword(input_pwd)の値はname属性で取得して、IF文で成功ページと失敗ページの遷移を分岐しています。 name属性を指定してテキストボックス内の値を取得する input_id = document.login_form.id.value; input_pwd = document.login_form.password.value; [4]まとめ いかがでしょうか。 ネットの情報を組み合わせて作っているだけなので詳しくはありませんが、 RPA(UiPath)で色々やるときの手段として作成してみました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

indesign スクリプト "段落スタイルを適用(構造内の選択された要素の参照に)

構造内の選択された要素の参照に段落スタイルを適用するスクリプトはこれで良いのかな・・・? 文字スタイルを消去の動作はスクリプトではどうやるのでしょう・・・解りません。 /* 構造内の選択された要素の参照に段落スタイルを適用する 更新 2021/05/05 */ // アプリ指定 #target "InDesign"; // スクリプト動作指定(高速) app.doScript(function(){ // スクリプト名 var scriptName = "段落スタイルを適用(構造内の選択された要素の参照に)"; // 適用数 var applyNumber = 0; // ダイアログ幅 var dialogWidth = 400; // ダイアログ高さ var dialogHeight = 150; // 段落スタイル選択用ダイアログ作成 var paragraphStyleSelectWindow = new Window("dialog",scriptName,[0,0,dialogWidth,dialogHeight]); // 段落スタイルの名前一覧 var paragraphStylesNameList = []; // 段落スタイルの数だけ繰り返す for(i = 0; i < app.activeDocument.paragraphStyles.length; i++){ // 段落スタイルを収集 paragraphStylesNameList.push(app.activeDocument.paragraphStyles[i].name); } // ドロップダウンリスト作成 var paragraphStylesDropdownlist = paragraphStyleSelectWindow.add("dropdownlist",[15,15,385,35],paragraphStylesNameList); // ドロップダウンリストの初期選択 paragraphStylesDropdownlist.selection = 0; // 次のスタイルへのチェックボックス作成 var nextStyleCheckBox = paragraphStyleSelectWindow.add("checkbox", [15,50,385,65], "選択された段落スタイルを適用して次のスタイルへ"); // 次のスタイルへのチェックボックスの選択 nextStyleCheckBox.value = true; // オーバーライドを消去のチェックボックス作成 var overrideEraseCheckBox = paragraphStyleSelectWindow.add("checkbox", [15,75,385,90], "オーバーライドを消去"); // オーバーライドを消去のチェックボックスの選択 overrideEraseCheckBox.value = true; // ボタンの幅 var buttonWidth = 80; // ボタンの高さ var buttonHeight = 25; // ボタンをウィンドウ下部中央に配置 paragraphStyleSelectWindow.add("button",[(dialogWidth / 2) - 10 - buttonWidth,dialogHeight - 10 - buttonHeight,(dialogWidth / 2) - 10,dialogHeight - 10],"適用",{name:"ok"}); paragraphStyleSelectWindow.add("button",[(dialogWidth / 2) + 10,dialogHeight - 10 - buttonHeight,(dialogWidth / 2) + 10 + buttonWidth,dialogHeight - 10],"キャンセル",{name:"cancel"}); // ダイアログを画面のセンターに paragraphStyleSelectWindow.center(); // ダイアログを表示 paragraphStyleSelectWindowShow = paragraphStyleSelectWindow.show(); // キャンセルの場合 if (paragraphStyleSelectWindowShow == 2){ exit(); } // 選択オブジェクトの数だけ繰り返す for(var i = 0; i < app.activeDocument.selection.length; i++){ // 選択オブジェクトが要素の場合 if(app.activeDocument.selection[i].constructor.name == "XMLElement"){ // 要素の参照がテキストまたはストーリーの場合 if(app.activeDocument.selection[i].xmlContent.constructor.name == "Text" || app.activeDocument.selection[i].xmlContent.constructor.name == "Story"){ // 適用数追加 applyNumber++; // 選択段落スタイル var selectParagraphStyle = app.activeDocument.paragraphStyles.item(paragraphStylesDropdownlist.selection.text); // 段落の数だけ繰り返す for(var ii = 0; ii < app.activeDocument.selection[i].paragraphs.length; ii++){ // 段落に段落スタイルを適用 app.activeDocument.selection[i].paragraphs[ii].applyParagraphStyle(selectParagraphStyle,overrideEraseCheckBox.value); // 選択段落スタイルが[段落スタイルなし]では無く、次のスタイルへがチェックボックスが選択されている場合 if(selectParagraphStyle != app.activeDocument.paragraphStyles[0] && nextStyleCheckBox.value == true){ // 次のスタイルを設定 selectParagraphStyle = selectParagraphStyle.nextStyle; } } } } } // 適用数表示 alert("適用数 " + applyNumber,scriptName); //スクリプト動作指定(高速)の続き },ScriptLanguage.JAVASCRIPT,[],UndoModes.FAST_ENTIRE_SCRIPT);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

レンダリングブロックに配慮したリソースの読み込み(CSS編)

はじめに こちらの記事はレンダリングブロックに配慮したリソースの読み込み(レンダリングの基本編)の続きです。 前述の記事を読んでおくと、当記事の内容も理解しやすいかもしれません。 やるべきこと CSSファイルが読み込まれるとパース後にCSSOM(CSS版のDOMのようなもの)の構築が行われます。 CSSOMの構築中はJavaScriptの実行やページのレンダリングがブロックされます。(DOMの構築はブロックしません。) しかし、以下の対策を行うことでこのような問題が解消されます。 1. CSSを非同期で読み込み 2. クリティカルCSSをインラインで記述 具体的にどのような記述をすれば良いのか紹介していきます。 CSSを非同期で読み込み CSSを非同期で読み込むとCSSOMの構築も非同期になり、JavaScriptの実行やレンダリングがブロックされるといった問題が解消されます。 CSSの非同期読み込みには2パターンあります。 注意 非同期の特性上CSSの適用遅れが発生し、スタイルが適用されていないコンテンツが表示されることがあります。(いわゆるFOUC) またJavaScriptにはCSSOMを取得・変更する機能があるため、原則としてCSSOMの構築が完了してから実行されるようになっています。 CSSやJavaScriptのどちらか、または両方を非同期で読み込むと実行順序が担保できなくなってしまい、JavaScriptでスタイルの制御をしている場合などは処理に影響が出る可能性があります。 レンダリングブロック対策に注力するあまり正しい処理が行われないのは本末転倒なので状況によって使い分けてください。 rel=preload属性を使った非同期読み込み <head> <link rel="preload" href="foo.css" as="style"> </head> <body>...</body> 特徴 IEなど一部ブラウザは非対応のためpolyfillが必要になります。 media・onload属性を使った非同期読み込み <head> <link rel="stylesheet" href="foo.css" media="print" onload="this.media='all'"> </head> <body>...</body> 特徴 media属性をprintに設定することで非同期でロードするようになります。 そのままでは印刷の際にしかスタイルが適用されないためonload属性を使い、読み込み完了後にmedia属性をallに変更します。 IEなどでも使用可能です。 クリティカルCSSをインラインで記述 ファーストビューに必要なCSSをインラインで、それ以外のCSSを非同期で読み込むようにします。 これによってFOUCを抑えつつ、CSSOM構築に伴うレンダリングブロックの影響を最小限にすることができます。 <head> <style>/* クリティカルCSSを記述 */</style> <link rel="preload" href="foo.css" as="style"> </head> <body>...</body> 特徴 クリティカルCSSの抽出はCritical Path CSS Generatorやnpmパッケージのcriticalなどのツールを使うと便利です。 以上がレンダリングブロックに配慮したCSSの読み込み方法になります。 また、レンダリングブロックの視点から考えたアンチパターン・おすすめできない方法についてもまとめました。 アンチパターン サイズの大きいCSSファイルをそのまま読み込み <head> <link href="foo.css" rel="stylesheet"> <script src="foo.js"></script> </head> <body>...</body> 推奨しない理由 ファイルの読み込みからCSSOMの構築が完了するまでレンダリングがブロックされます。(DOMの構築はブロックしません。) 読み込みが完了するまでは何も表示されないため、クライアントの回線状況によってはUXに影響が出ます。 CSSの直後に読み込んでいるJavaScriptは直前までのCSSOM構築が完了してから実行されます。(scriptタグにasync・defer属性を付与した場合はこの影響を受けず非同期で実行されます。) インラインCSSでも同様です。 <body>内で読み込み HTML5.2からbody内でも外部CSSを読み込めるようになりました。 ※特に有用な場面が思いつきませんでしたがピックアップしました。 <head>...</head> <body> <p>テキスト1</p> <link href="foo.css" rel="stylesheet"> </body> 推奨しない理由 ファイルの読み込みからCSSOMの構築が完了するまでレンダリングがブロックされます。(DOMの構築はブロックしません。) 読み込みが完了(CSSOM構築)するまでは何も表示されないため、クライアントの回線状況によってはUXに影響が出ます。 CSS-injectedでの読み込み CSS-injectedは外部リソース読み込みのソースコードを出力するインラインJSです。(以下の記述を参照) CSS-injected 実行前 <head> <script> const link = document.createElement('link'); link.href = 'foo.css'; link.rel = 'stylesheet'; const head = document.getElementsByTagName('head')[0]; head.appendChild(link); </script> </head> <body>...</body> CSS-injected 実行後 <head> <link href="foo.css" rel="stylesheet"> </head> <body>...</body> 推奨しない理由 読み込みとCSSOM構築が非同期で行われますが、JavaScriptの実行からCSSの読み込み・CSSOM構築が完了するまではスタイルが適用されていないページが表示されます。 レンダリングブロック対策のまとめとポイント 外部CSSは非同期で読み込む。 サイズの大きいCSSファイルを同期的に読み込まない。 クリティカルなCSSはその他のCSSと切り離してインラインで記述する。 非同期の読み込みはJavaScriptの処理も考慮して指定する。 参考URL ページの生成:ブラウザーはどのように動作するか https://developer.mozilla.org/ja/docs/Web/Performance/How_browsers_work フロントエンドのパフォーマンスを徹底解説!ブラウザの気持ちで理解するHTML/Javascript/CSSの話 https://techblog.raccoon.ne.jp/archives/53180280.html rel=”preload”を極めるために必要な2種類のプリロード機能 https://techblog.raccoon.ne.jp/archives/1575956867.html
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Vue 2】Vuexチートシート

Vuexとは コンポーネント間でデータを共有するため状態管理ライブラリ いわゆる、グローバル変数のようなものを定義し操作できる 使い方 これ以降、VueCLIで作成を想定して記載 1. Vuexのインストール Vuexのインストール $ npm install vuex 2. /src直下にstore.jsを作成 このへんの場所に関してはプロジェクトに応じて設定する 図. 今回のプロジェクトのディレクトリ構成 3. main.jsのVueインスタンスにVuexを登録 main.js import Vue from 'vue' import App from './App.vue' import store from './store' // 追加行 Vue.config.productionTip = false new Vue({ store, // 追加行 render: h => h(App), }).$mount('#app') 4. store.jsおよびVueコンポーネントを実装 store.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) // Vuexインスタンス生成 export default new Vuex.Store({ // state: Vuexで管理する状態を定義 state: { count: 0, // 1 name: 'MouMou', password: 'hoge' }, // getters : stateの値を取得する処理を定義 // 引数のstateは上で宣言した状態管理オブジェクト getters: { count: state => state.count, // 2 name: state => state.name, // 3 password: state => state.password, // 3 }, // mutations : stateの値を変更する処理を定義 // 引数のstateは上で宣言した状態管理オブジェクト // 非同期処理に対応していない mutations: { setCount(state, newCount) { // 4 state.count = newCount }, setName(state, newName) { // 5 state.name = newName }, setPassword(state, newPassword) { // 5 state.password = newPassword } }, // actions : mutationを呼び出す処理を定義 // 非同期も対応している actions: { setCountAction({ commit }, newCount) { // 6 commit('setCount', newCount) }, setNameAction({ commit }, newName) { // 7 commit('setName', newName) }, setPasswordAction({ commit }, newPassword) { // 7 commit('setPassword', newPassword) }, } }) App.vue (他コンポーネントでも同様に記載できる) <template> <div id="app"> <!-- state --> <p>1. count = {{countDirect}}</p> <!-- getters --> <p>2. count = {{count}}</p> <p>3. name = {{name}}</p> <p>3. password = {{password}}</p> <!-- mutations --> <p><button @click="setCount">4. count = {{count}}</button></p> <p><button @click="setName('Qiita')">5. name = {{name}}</button></p> <p><button @click="setPassword('huga')">5. password = {{password}}</button></p> <!-- actions --> <p><button @click="setCountAction">6. count = {{count}}</button></p> <p><button @click="setNameAction('Vuex')">7. name = {{name}}</button></p> <p><button @click="setPasswordAction('huge')">7. password = {{password}}</button></p> </div> </template> <script> // map系を使用する場合importする import {mapGetters} from 'vuex' import {mapMutations} from 'vuex' import {mapActions} from 'vuex' export default { computed: { // [1.state] 直接操作(非推奨) countDirect() { return this.$store.state.count }, // [2.getters] stateの値を取得 count() { return this.$store.getters.count }, // [3.getters] 一括でgettersを設定 ...mapGetters(['name','password']), }, methods: { // [4.mutations] stateの値を変更 setCount() { this.$store.commit("setCount", 1) // 第二引数はmutationに渡す値 }, // [5.mutations] 一括でmutationsを設定 ...mapMutations(['setName','setPassword']) , // [6.actions] mutationsを起動 setCountAction() { this.$store.dispatch('setCountAction', 2) // 第二引数はmutationに渡す値 }, // [7.actions] 一括でactionsを設定 ...mapActions(['setNameAction', 'setPasswordAction']) } } </script> 図. 表示画面 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScriptの条件分岐switchについて

JavaScriptのswitchは同値演算子(===)に特化した条件分岐です。 同値演算子とは等値演算子(==)よりも厳密に比較したい時に使われます。 switchの構文は次のように書きます。 switch(式){ case 値1: // 「式 === 値1」である時に実行したい処理を書く break;//ここでswitch文を抜ける意味 case 値2: // 「式 === 値2」であると時に実行したい処理を書く break;//ここでswitch文を抜ける意味 default: // 式の値がすべての値に合致しない時に実行したい処理を書く break; } 次に例文を書いてみます。 var n = 1; switch(n) { case 1: console.log('数値は1です'); break; case 2: console.log('数値は2です'); break; case 3: console.log('数値は3です'); break; default: console.log('範囲外です'); break; } これを実行すると のように出力されました。 この場合変数nに1が代入されcase1に当てはまるので'数値は1です'が実行されました。 次にどれにも当てはまらない4を代入してみます。 var n = 4; switch(n) { case 1: console.log('数値は1です'); break; case 2: console.log('数値は2です'); break; case 3: console.log('数値は3です'); break; default: console.log('範囲外です'); break; } 実行結果 case1,2,3どれも当てはまらないのでdefaultが実行されました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

画像ファイルをドラッグ&ドロップでブラウザのアプリケーションに取り込ませる方法

画像ファイルをドラッグ&ドロップでブラウザのアプリケーションに取り込ませる方法を調べました。 例えば、以下のような写真をカレンダー形式で管理するアプリケーションを作るとして、画像ファイルをドラッグ&ドロップで表示できれば便利かと思います。 JavaScriptだけを使った簡易な実装方法と、PHPを使ったきちんとした(つもりの)実装方法の2パターンを書きます。 1.JavaScriptだけで実装 calender.html <table> <tr> <td id="box1">ボックス1</td> <td id="box2">ボックス2</td> </tr> </table> drag_drop.js $(function () { $("td").on('dragover', function (e) { e.stopPropagation(); e.preventDefault(); }); $("td").on('drop', function (e) { e.stopPropagation(); e.preventDefault(); var boxid = $(this).attr("id"); var items = e.originalEvent.dataTransfer.items; var file = items[0].getAsFile(); var reader = new FileReader(); reader.readAsDataURL(file); reader.onloadend = function() { $("#" + boxid).append("<img src=" + reader.result + " width=130>"); }; }); }); このコードでたしかに画像をブラウザに表示させることはできるのですが、画像を保存できないため、実用上はあまり意味がないものです。 aタグに画像を挿入し、aタグのDownload属性を使ってダウンロードフォルダに格納することも試したのですが、使い勝手はあんまり良くなかったです。 2.PHPを使って実装 calender.html <table> <tr> <td id="box1"> ボックス1 <?php if ($box == "box1") { print("<img src=\"" . $data . "\" width=130>"); } ?></td> <td id="box2"> ボックス2 <?php if ($box == "box2") { print("<img src=\"" . $data . "\" width=130>"); } ?></td> </tr> </table> drag_drop.js $(function () { $("td").on('dragover', function (e) { e.stopPropagation(); e.preventDefault(); }); $("td").on('drop', function (e) { e.stopPropagation(); e.preventDefault(); var boxid = $(this).attr("id"); var items = e.originalEvent.dataTransfer.items; var file = items[0].getAsFile(); var reader = new FileReader(); reader.readAsDataURL(file); reader.onloadend = function() { $("#" + boxid).append("<form id=\"upload" + boxid + "\" action=\"calender.php\" method=\"POST\"></form>") $("#upload" + boxid).append("<input type=\"hidden\" name=\"day\" value=\"" + boxid + "\">"); $("#upload" + boxid).append("<input type=\"hidden\" name=\"data\" value=\"" + reader.result + "\">"); var form = $("#upload" + boxid); form.submit(); }; }); }); calender.php function get_post_data($key) { $str = ''; if (isset($_POST[$key]) === TRUE) { $str = $_POST[$key]; } return $str; } $box = ""; $data = ""; if ($_SERVER['REQUEST_METHOD'] === "POST") { $box = get_post_data('box'); $data = get_post_data('data'); } include_once "calender.html"; これで画像をブラウザに表示させることができます。 あとは画像データのDBへの出し入れと、ブラウザへの描画の部分を修正すれば、意図した通り画像ファイルの取り込みをドラッグ&ドロップで実現できます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

コールバック関数とは

コールバック関数とは 関数の引数に渡された関数のことをコールバック関数といいます。 呼び出された関数が逆に関数を呼び出す側になるのでコールバックと言います。 実際にコードをみてみましょう。 // ②confirmed関数が呼び出される function confirmed(fn) { if(window.confirm("OKを押して下さい")) { // ③引数で受け取った関数を呼び出す fn() } }; // ①confiremed関数を呼び出す confirmed(function () { console.log("OKを押しました"); }); このコードを実行してみます。 ポップアップでOKを押してくださいと出てきます。 OKを押し、コンソールを確認するとOKを押しましたと表示されています。 処理を追ってみます。 まず最初にconfirmed関数を呼び出します。 この時、confirmed関数に対し引数で関数を受け渡しています。 JavaScriptでは関数もオブジェクトの一つであるため、関数を引数として指定することも可能です。 呼び出されたconfirmed関数は処理を実行します。 処理を実行するのでブラウザ上にポップアップでOKを押してくださいが表示されます。 ユーザーがOKを押下すると、呼び出された側であったはずのconfirmed関数が引数で受け取った関数を呼び出しています。 その結果console.log("OKを押しました")の処理が実行されるので、コンソールにOKを押しましたと表示されます。 最初は呼び出された側であったconfirmed関数が処理を実行した後、逆に関数を呼び出す側になったと思います。 これがコールバック関数です。 コールバック関数が主に使われるケース 非同期処理を行う時に使用する事が多いです。 非同期処理というのは、誰かに仕事を任せる事で自分は別の仕事を進める事ができます。(つまり同時に複数処理を行える。) この場合コールバック関数は、非同期処理でお願いした仕事が終わった後に、特定の処理を指定する時に使われます。 実際にsetTimeout関数を使用した例をみてみましょう。 setTimeout( コールバック関数 , 時間の指定 ) 第一引数にコールバック関数、第二引数に時間の指定をする事ができます。 setTimeoutは時間を指定し、一定時間後に一度だけコールバック関数を実行する事ができます。 const Bye = function(){ console.log('さよなら!'); } console.log('おはよう!') setTimeout(Bye, 3000); console.log('調子はどう?'); >> おはよう! >> 調子はどう? // 3秒後にByeが実行される >> さよなら! 処理を流れをみてみます。 console.log('おはよう!')を実行した後、setTimeoutが発火します。 このsetTimeoutは非同期処理のため、3秒間待つようにお願いし、その間に自分は次の処理に進む事ができます。 その結果console.log('調子はどう?')を実行し、そして3秒待った後Byeが実行され、さよなら!が表示されます。 まとめ コールバック関数は関数の引数に渡された関数のことを指します。 非同期処理で使用する場合、お願いした仕事(非同期処理)が終わった後に、別の処理を指定する際にコールバック関数が使われます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

最強のHTAを求めて。

HTAのこれまでと現状については面倒なので略すが、現状HTAはまだ動くには動くが、デフォルトのままではIE7相当の機能でしか動かず、X-UA-Compatibleの指定でIE10以上に設定すると、HTA固有のHTA:APPLICATIONタグの機能が大きくスペックダウンし、起動パラメータが参照できなくなったり、外観や挙動の制御が制限されたりとかになってしまう。 それを回避するために、起動用のHTAを使って、旧バージョンでのフルスペックの機能設定を行った上で、本命のHTAにリダイレクトする、という方法が編み出された。 IE10モード以上のHTAでHTA:APPLICATIONオプションを使う方法 | while(isプログラマ) https://am-yu.net/2015/04/26/ie10-ie11-htaapplication/ これは大変すばらしい技だが、構成が2つHTAに分かれてしまう、という欠点がある。そこで1つのHTAでこれを実現できないものか?とあれこれ考えて、とりあえず動くものが出来たのでメモ代わりにここに残す。 基本的な考え方は以下の通り。 ・バッチファイルにWSH/JScriptとHTAを埋め込む。 ・JScriptで起動用のHTAをテンポラリに生成し、元のHTAのHTA:APPLICATIONタグをコピーする。 ・起動用HTAから元のHTAをリダイレクト表示してテンポラリファイルを削除する。 そのためのポイントは以下の通り。 ・基本的な考えは前述の「IE10モード以上のHTAでHTA:APPLICATIONオプションを使う方法」。 ・Chakraエンジンでは<!--がコメント扱いになることを利用して、バッチファイルとして記述したHTAに、自身をChakraエンジン用JScriptとして起動するバッチコマンドをHTAのコメントとして記述する。(上部) ・さらに同様にHTAのコメントとして起動用HTAの生成と実行を行うChakraエンジン用JScriptを記述する。(下部。HTA部分を/* */ でコメントアウトする都合上、下部に */ の追加が必要なので、ついでにコード部分を下に置いた。) 今回はそこまでやってないが、WSH/JScriptからHTAを起動するので、コマンドラインパラメータをオブジェクトにしてJSON化&encodeURIComponentしてgetパラメータで渡せば、コマンドライン・パラメータをHTAに引き渡せる。HTA:APPLICATIONのcommandLineプロパティを解析して取得するよりは全然楽なはず。 で、これがコード。バッチとして起動するのと、MSHTAコマンドから起動するのとでの微妙な違いをご覧いただきたい。 SampleHTA.bat <!-- : ^ /* @cscript //nologo //E:{1b7cd997-e5ff-4932-a7a6-2a9e636da385} "%~f0" %* @exit /B :↑でバッチ自体は終了するので、ここからはバッチからは無視される。 :↓ここに HTA コードを記述する (/*~*/のコメントは使えないので注意 */ /* /////////////////////////////////////////////////////////////////// --> <!DOCTYPE html> <html lang="ja"> <!-- サンプルダミーHTA --- ボタンを押しても何も起きません。 --> <head> <meta http-equiv="content-type" content="text/html; charset=Shift_JIS"> <meta http-equiv="content-script-type" content="text/javascript"> <meta http-equiv="content-style-type" content="text/css"> <meta http-equiv="X-UA-Compatible" content="IE=EDGE" /> <title>input box</title> <hta:application id="oHTA" applicationname="input box" border="thick" caption="yes" maximizebutton = "no" minimizebutton = "no" selection = "no" showintaskbar="yes" singleinstance="yes" sysmenu="yes" windowstate="nomal"> <style type="text/css"> * { margin: 0; padding: 0; } </style> <link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/ui-lightness/jquery-ui.css" /> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js"></script> </head> <body onresize="window.resizeTo(432,188);" onLoad="window.resizeTo(432,188);" style="background-color: whitesmoke;" > <div style="position: absolute; left: 3mm; top: 3mm; font-size: 10pt;"> 入力してください。 </div> <input id="text1" type="text" name="text1" size="68" style="position: absolute; left: 3mm; bottom: 3mm; font-size: 10pt; height: 1.5em; "> <button id="btnOK" type="button" name="btnOK" style="position: absolute; right: 3mm; top: 3mm; font-size: 10pt; height: 2em; width: 7em">OK</button> <button id="btnCAN" type="button" name="btnCAN" style="position: absolute; right: 3mm; top: 13mm; font-size: 10pt; height: 2em; width: 7em">キャンセル</button> <script type="text/javascript"> // </script> </body> </html> <!-- */ ///////////////////////////////////////////////////////////////// // ↑ HTA コードここまで。以下は起動用コード genHTAkicker( WScript.ScriptFullName )(); // HTA 再起動 function genHTAkicker( file ) { var fso = typeof(fso)==='undefined' ? WScript.CreateObject('Scripting.FileSystemObject') : fso; var mch, str, xuae, ie=7, app, hta; file = fso.GetAbsolutePathName( file ); // str = _.file2text( file ); var f = fso.OpenTextFile( file, 1 ); // iomode 1:ForReading if( ! f.AtEndOfStream ) str = f.ReadAll(); f.close(); // 雑な正規表現(1) X-UA-Compatible 定義の抽出 if( mch = str.match(/\<.*"X\x2DUA-Compatible".*\>/) ) { xuae = mch[0]; if( mch = xuae.match(/"IE=([^"]+)"/) ) ie = mch[1]; } // 雑な正規表現(2) HTA:APPLICATION 定義の抽出 if( mch = str.match(/\<HTA\x3AAPPLICATION[\S\s]*?\>/im) ) app = mch[0]; if( parseInt(ie) <=9 ) return void 0; hta = "\ <!DOCTYPE html>\n\ <html>\n\ <head>\n\ <meta http-equiv='X-UA-Compatible' content='IE=9' />\n\ <meta http-equiv='refresh' content='0;URL=" + file + "?kicked'>\n\ " + app + "\n\ </head>\n\ <body>\n\ <script>\n\ var fso = new ActiveXObject('Scripting.FileSystemObject');\n\ window.addEventListener('unload', function(event) {\n\ fso.DeleteFile('@@@@@@@@');\n\ });\n\ <\x2Fscript>\n\ </body>\n\ </html>"; // kicker生成 return function kickHTA(){ var fso = typeof(fso)==='undefined' ? WScript.CreateObject('Scripting.FileSystemObject') : fso; var WshShell = typeof(WshShell)==='undefined' ? WScript.CreateObject('WScript.Shell') : fso; // var tempfile = _.genTempPathEasy(); var tempfile = ( ((new Date()).toLocaleString()).replace( /([^\d])(\d)(?=[月日:]|$)/g, "$10$2" ) ).replace( /[^\d]+/g, "" ); tempfile = fso.BuildPath( fso.GetSpecialFolder(2), tempfile ); hta = hta.replace( /@@@@@@@@/, tempfile.replace(/\\/g,"/") ); // _.text2file( hta, tempfile ); var f = fso.CreateTextFile( tempfile, true ); f.Write(hta); f.close(); // WshShell.Run( 'MSHTA ' + tempfile + ' & del ' + tempfile, 1, true ); WshShell.Run( 'MSHTA ' + tempfile, 1 ); } } // この行は消さないこと。 --> 作るには作った。が、大袈裟すぎる。微妙な違いのためにこれかよ。どうしても1ファイルにしたいとき以外は2ファイル構成にする方がお手軽だし、IE10以降固有の機能まで必要ないなら、IE=9を指定してやればES5で使えるし、commandLineプロパティも含めHTA:APPLICATIONの機能がフルセットで動くので、それでいいじゃないのよ。というのが結論である。やれやれ。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.js~イベント処理~

概要 フォームの入力の読み取り、送信するまでのプログラムについての記事です。 v-on,v-modelについて主に取り上げています。 イベント発生 今回のフォームの実装では、ユーザーが入力して送信ボタンを押すのがイベント発生となります。 イベントを設定します。 HTML index.html <form @submit.prevent ="addItem"> <input type="text" v-model="newItem"> <input type="submit" value="add"> </form> イベントはsubmitです。 イベント処理を実装するのはv-onです。(上記では@sbmit)となっています。 更に今回のイベントは、ユーザーからの入力内容を受け取り反映したいので、input type="text"から値を受け取ります。 v-model v-model="データオブジェクトプロパティ" v-on v-on="...." (@イベント名="") sbmitされたときのメソッドを指定します。今回は、addItemです。 更に今回はボタンタグにsubmitを使用しています。それにより、ページ変移が起きてしまうのでpreventDefaultメソッドを使用します。 index.html @submit.prevent と記述します。 Vue つづいて、Vueの実装内容です。 index.js data:{ newItem:'', lists:[ 'list1', 'list2', 'list3' ] }, 双方向データバインディング 先程、v-modelで指定したプロパティはnewItemです。 現在こちらのプロパティは空に設定しています。こちらに文字列を入れてみました。 すると、テキストボックスに初期値が反映されていました。 これは、双方向データバインディングといいます。Vue.jsのフォーム開発で大切になります。 データオブジェクトからテキストボックスの反映はもちろん。テキストボックスからの反映も可能にします。(データオブジェクトとテンプレート状態を同期する) ちなみに、v-modelを利用した場合はテキストボックスでHTMLから指定されたValue属性は無効になります。 index.js methods:{ addItem: function() { this.lists.push(this.newItem); this.newItem = ''; } } 次に送信されたときの処理についてです。methodsというキーでイベントオブジェクトを作ります。 先程のHTMLで指定したaddItemで処理を書いていきます。 今回の処理内容は、submitしたときにlistsという配列にプッシュします。 data内のlistにはthisでアクセスすることが出来ます。this.lists.pushとすることで追加することが出来ます。何をプッシュするのかv-modelで取得したプロパティですね。 値を送信した後に値がテキストボックスからなくなるようにthis.newItem = ''空文字にします。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

同期処理・非同期処理の概要

前書き 同期処理や非同期処理の概要についてまとめてみました。 コールバック関数、Promise、async / awaitなど今後まとめていきたいと思います。 同期処理・非同期処理の説明の前に PCの計算時間について 例 時間 CPUの1サイクル およそ0.3ナノ秒 Floatの足し算 1.2ナノ秒 メモリのデータを参照する速さ 120ナノ秒 SSDからのデータの読み取り 100マイクロ秒(マイクロ秒はナノ秒の1000倍) 日本からシリコンバレにインターネットでやりとりする時間 100ミリ秒(ミリ秒はマイクロ秒の1000倍) CPUの1サイクルを1秒とした場合 例 時間 CPUの1サイクル 1秒 Floatの足し算 4秒 メモリのデータを参照する速さ 6分 SSDからのデータの読み取り 4日 日本からシリコンバレーにインターネットでやりとりする時間 およそ10年 CPUで計算したり、メモリからデータを参照する事と比べて、インターネットを通じてデータを取得するというのはものすごく時間がかかる事が分かります。 同期処理とは コードを順番に処理していき、ひとつの処理が終わるまで次の処理は行わない処理の事です。 どんなに時間のかかる処理を行っていたとしても、同期処理の場合はその処理が終わるまで待ちます。 二つ例を出してみます。 ネットワーク通信の場合 同期処理でネットワーク通信を行った場合、時間のかかるインターネット通信が終わってからじゃないと次の処理を行うことができません。 CPUの1サイクルを1秒とした場合、ネットワーク通信は10年かかります。 その間に色々計算できそうですが、10年後にならないと他の処理ができないのでリソース的に勿体無いですよね。 人間世界の場合 人間世界を例として以下のことをしたいとします。 お風呂に入る ->自分 食洗機で食器を洗う ->食洗機 食器を片付ける ->自分 同期処理の場合だと自分がお風呂に入り終わったら食洗機で食器を洗い、洗い終わったら自分が干すという処理になります。 これだと食洗機が皿を洗ってる間に自分というリソースは使用されず放置状態になります。 非同期処理とは 処理が終わるのを待たずに、同時に複数の処理を実行することができます。 誰かに仕事をお願いする事で、自分は他の仕事を進める事ができる仕組みです。 その結果、複数処理を実行する事ができます。 先ほど例にあげたネット通信も非同期で行った場合、ネット通信の結果を待たず、CPUの計算も行う事ができます。 人間世界の例も同様です。 食洗機に頑張って食器を洗ってもらう間に自分はお風呂に入ってしまいます。 結果として同期処理より早く処理を終える事ができます。 このように非同期処理では誰かに仕事をお願いすることで自分は別の作業を進める事ができ、結果として同時に複数の処理を行う事ができます。 非同期処理の難しさ 非同期通信で複数処理を行った場合、どちらの作業が先に終わるかが分かりません。 そのためどちらが先に処理が終わってもいいように、プログラムを書いておく必要があります。 その点同期通信だと順番に処理を行い、その処理が終わるまで待つのでどちらが先に終わるかを考えなくていいですよね。 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

同期処理・非同期処理について

前書き 同期処理や非同期処理の概要をまとめてみました。 コールバック関数、Promise、async / awaitなど今後まとめていきたいと思います。 同期処理・非同期処理の説明の前に PCの計算時間について 例 時間 CPUの1サイクル およそ0.3ナノ秒 Floatの足し算 1.2ナノ秒 メモリのデータを参照する速さ 120ナノ秒 SSDからのデータの読み取り 100マイクロ秒(マイクロ秒はナノ秒の1000倍) 日本からシリコンバレにインターネットでやりとりする時間 100ミリ秒(ミリ秒はマイクロ秒の1000倍) CPUの1サイクルを1秒とした場合 例 時間 CPUの1サイクル 1秒 Floatの足し算 4秒 メモリのデータを参照する速さ 6分 SSDからのデータの読み取り 4日 日本からシリコンバレーにインターネットでやりとりする時間 およそ10年 CPUで計算したり、メモリからデータを参照する事と比べて、インターネットを通じてデータを取得するというのはものすごく時間がかかる事が分かります。 同期処理とは コードを順番に処理していき、ひとつの処理が終わるまで次の処理は行わない処理の事です。 どんなに時間のかかる処理を行っていたとしても、同期処理の場合はその処理が終わるまで待ちます。 二つ例を出してみます。 ネットワーク通信の場合 同期処理でネットワーク通信を行った場合、時間のかかるインターネット通信が終わってからじゃないと次の処理を行うことができません。 CPUの1サイクルを1秒とした場合、ネットワーク通信は10年かかります。 その間に色々計算できそうですが、10年後にならないと他の処理ができないのでリソース的に勿体無いですよね。 人間世界の場合 人間世界を例として以下のことをしたいとします。 お風呂に入る ->自分 食洗機で食器を洗う ->食洗機 食器を片付ける ->自分 同期処理の場合だと自分がお風呂に入り終わったら食洗機で食器を洗い、洗い終わったら自分が干すという処理になります。 これだと食洗機が皿を洗ってる間に自分というリソースは使用されず放置状態になります。 非同期処理とは 処理が終わるのを待たずに、同時に複数の処理を実行することができます。 誰かに仕事をお願いする事で、自分は他の仕事を進める事ができる仕組みです。 その結果、複数処理を実行する事ができます。 先ほど例にあげたネット通信も非同期で行った場合、ネット通信の結果を待たず、CPUの計算も行う事ができます。 人間世界の例も同様です。 食洗機に頑張って食器を洗ってもらう間に自分はお風呂に入ってしまいます。 結果として同期処理より早く処理を終える事ができます。 このように非同期処理では誰かに仕事をお願いすることで自分は別の作業を進める事ができ、結果として同時に複数の処理を行う事ができます。 非同期処理の難しさ 非同期通信で複数処理を行った場合、どちらの作業が先に終わるかが分かりません。 そのためどちらが先に処理が終わってもいいように、プログラムを書いておく必要があります。 その点同期通信だと順番に処理を行い、その処理が終わるまで待つのでどちらが先に終わるかを考えなくていいですよね。 参考
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScriptで関数型言語を作ろう(7) 型の表現・式の型チェック

今回は珍しく,前回 の理解度チェックの答え合わせから. 前回,こんなプログラムに対してHelloWorldを出力させるところまでは確認できました. "Hello".add("World") また,次のように存在しないメソッドを含むプログラムを実行させると,SemanticError: addd is not definedのような意味エラーをちゃんと出してくれる,というところも確認できていると思います. "Hello".addd("World") では,次はどうでしょう.確か,前回「文字列にはaddしかなくて,subやらmulやらは使えない仕様です」と断っておいたので,エラーになってほしいところです. "Hello".sub("World") こうなりました: const {Num, Str}=runtime; return Str("hello").sub(Str("world")); TypeError: Str(...).sub is not a function at eval (eval at run (C:\bin\Dropbox\workspace\tinyfunc\index.js:42:18), <anonymous>:5:25) at run (C:\bin\Dropbox\workspace\tinyfunc\index.js:43:17) at test (C:\bin\Dropbox\workspace\tinyfunc\index.js:16:9) (略) やった!エラーが出た! と思った方は残念でした.これ,前回我々がちゃんと仕込んだSemanticErrorではありません.その証拠に const {Num, Str}=runtime; return Str("hello").sub(Str("world")); というコードが生成されてしまっています.SemanticErrorが出た場合,その場で例外となるので,コードが生成されない点に注意しましょう. このプログラムにおいては「コードがされちゃって,実行したら実行時エラーになった」にすぎず,処理系がちゃんと事前にエラーをチェックできていません. では,なぜ"Hello".addd("World")はちゃんとSemanticErrorになったのに,"Hello".sub("World")は我々の仕込んだエラーチェックをすり抜けて実行されて(実行時エラーになって)しまったのでしょうか. ポイントはSemantics.tsです. lang/Semantics.ts const numberTypeMembers=new Set(["add","sub"]); export function check(expr: ValueExpression) { const E=(...messages:any[])=>new SemanticError( ...messages); console.log("Checking", expr); if (expr instanceof NumberLiteral) { } else if (expr instanceof StringLiteral) {//追加 } else if (expr instanceof Identifier) { } else if (expr instanceof MemberAccess) { check(expr.left); //ここで存在しないメンバーのチェックをしている if (!numberTypeMembers.has(expr.name.text)) { throw E(expr.name.text, " is not defined"); } } else if (expr instanceof Call) { check(expr.left); } else { throw invalid(expr); } } このif (!numberTypeMembers.has(expr.name.text)) { の部分で,.addやら.adddやら.subやらがメンバ名として正しいかどうかチェックしているのですが,numberTypeMembersの中身が const numberTypeMembers=new Set(["add","sub"]); ,つまり「addかsubならOK,それ以外はSemanticError」というチェックをしています.(この部分は理解度チェックをしている方はもう少し増えてますね) しかし,文字列型にはaddしかないので,subがOKのわけがないんですが,この処理ではOKにしてしまっています. そもそも文字列型のメンバーのチェックでnumberTypeMembersを使ってはまずいですよね. では,どうするのか,というのが今回のテーマです. 式の型チェック } else if (expr instanceof MemberAccess) { check(expr.left); //ここで存在しないメンバーのチェックをしている if (!numberTypeMembers.has(expr.name.text)) { throw E(expr.name.text, " is not defined"); } exprがMemberAccess ,つまりa.bのような形の式の場合の処理だけ抜き出してみました. MemberAccessには,a.bのaの側をleft,bの側の名前をnameで管理しています. expr.leftの部分に数値が来ていればaddやらsubやら,他にもmulやらdivやらも使ってよい expr.leftの部分に文字列が来ていればadd以外はダメ という場合分けが必要になってきます. そこで,expr.leftの部分がどんな型なのかを調べる関数を新たに定義しましょう.Semantics.tsの適当なところ(checkメソッドの上あたり)にgetTypeという関数を作成しましょう. export function getType(expr: ValueExpression):Type { //式exprの型を返す } で,これはエラーになります. lang/Semantics.ts:5:48 - error TS2304: Cannot find name 'Type'. 5 export function getType(expr: ValueExpression):Type { ~~~~ Typeなんていう型はないですよね.はい,では今から作りましょう.lang/Types.tsというファイルを新規作成しましょう. lang/Types.ts import { Identifier } from "./Expressions"; export class StructType { constructor(public name:Identifier, public members:Member[]) {} } export class Member { constructor(public name:Identifier) {} } export type Type=StructType; StructTypeって何かというと,今問題になっている数値型や文字列型を表します.structというとC言語の「構造体」を思い出すので,数値なのに構造体? と思うかもしれませんが,この言語では,3.addみたいに,数値でも構造体っぽく「ドット+名前」でアクセスできるので,構造体扱いにしています. この.addの部分を「メンバー」と呼びます.StructTypeには複数のメンバーを定義でき,それらがmembersというフィールドに格納されます. Memberの定義は,とりあえず名前だけです.型やメンバーの名前はExpressions.tsで定義したIdentifierを使っています. 最後の行で「Typeは,StructTypeのことです」,と書いてあります.後でStructType以外のものもTypeの仲間として追加される予定です. では,これを使って,数値型や文字列型を定義します. lang/Types.ts //今まで書いたものの下に追加 const nMembers=[ new Member(new Identifier("add")), new Member(new Identifier("sub")), ]; export const numberType=new StructType(new Identifier("Number"), nMembers); const sMembers=[ new Member(new Identifier("add")), ]; export const stringType=new StructType(new Identifier("String"), sMembers); そして,これを使って,Semantics.tsのgetTypeを定義してみましょう. lang/Semantics.ts import { Type, stringType, numberType } from "./Types"; //中略 export function getType(expr: ValueExpression):Type { if (expr instanceof StringLiteral) { return stringType; } else { return numberType; } } //後略 とりあえず,文字列リテラル("abc"とか)は文字列型,それ以外は数値型にしておきましょう(「おい,そんなんで大丈夫か」と思った方,お見事.大丈夫じゃないです! 理解度チェックで大丈夫じゃない例を挙げてみましょう) そして,StructTypeからメンバーを取り出す関数も作っておきます.なお,指定した型の指定した名前のメンバーがない場合はSemanticsErrorにしています. lang/Semantics.ts //中略 export function getMember(type:StructType, name:Identifier):Member { for (const member of type.members) { if (member.name.text===name.text) return member; } throw new SemanticError("member is not defined"); } //後略 最後に,checkの部分を書き換えましょう. lang/Semantics.ts //中略 export function check(expr: ValueExpression) { const E=(...messages:any[])=>new SemanticError( ...messages); console.log("Checking", expr); if (expr instanceof NumberLiteral) { } else if (expr instanceof StringLiteral) {//追加 } else if (expr instanceof Identifier) { } else if (expr instanceof MemberAccess) { check(expr.left); const leftType=getType(expr.left);//expr.leftの型を取得 getMember(leftType, expr.name);//その型からメンバーを取得 } else if (expr instanceof Call) { check(expr.left); } else { throw invalid(expr); } } //後略 では,これで実行してみます(tscを忘れないように). まず数値型 test/single.txt 3.add(2) ↑これは正しく実行されて5になります test/single.txt 3.sub(2) ↑これもOK(以前の理解度チェックでちゃんと引き算の仕組みを作っていれば) test/single.txt 3.addd(2) ↑これはちゃんとSemanticsErrorになってくれるのでOK. test/str.txt "hello".add("world") ↑これは正しく実行されてhelloworldになります test/str.txt "hello".addd("world") ↑これはちゃんとSemanticsErrorになってくれるのでOK. さて,今回問題になっていた(SemanticsErrorにならなくて,実行時エラーになっちゃうもの)を実行してみましょう. test/str.txt "hello".sub("world") (中略) Checking StringLiteral { value: 'hello' } SemanticError: SemanticError: member is not defined at getMember (C:\bin\Dropbox\workspace\tinyfunc\lang\Semantics.js:23:11) at check (C:\bin\Dropbox\workspace\tinyfunc\lang\Semantics.js:38:9) at Object.check (C:\bin\Dropbox\workspace\tinyfunc\lang\Semantics.js:44:9) at run (C:\bin\Dropbox\workspace\tinyfunc\index.js:36:17) ちゃんとコードが生成されず,SemanticsErrorになりました. 理解度チェック (1) メンバーが見つからなかったときのエラーを親切にしてみましょう: Before: SemanticError: SemanticError: member is not defined After: SemanticError: SemanticError: member 'sub' is not defined in type 'String' (2) この状態でも相変わらず「SemanticsErrorにならなくて,実行時エラーになっちゃうもの」は存在します.どんなコードでしょう? 前回まで書いたコードの中にヒントがあるかもしれません. ここまでのソースコード
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScript 文字列を反転させたい。結合文字とサロゲートペア対応。

文字列を反転させたい|nona|note https://note.com/ttuusskk/n/n6f874b0274bd 反転させたい人は多いらしい。スジャータをタ~ジャスに変えたいとかなんとか。しらんけど。 こんなふうにやろうよね。ってことのようです。 const split = require('graphemesplit'); // npm i graphemesplit const str0 = '👨‍👩‍👧‍👦🌕の夜に𩸽食べたい' const str1 = str0 + 'がき'; const str2 = str0 + "\u304b\u3099\u304d"; console.log(str1); // 👨‍👩‍👧‍👦🌕の夜に𩸽食べたいがき console.log(str2); // 👨‍👩‍👧‍👦🌕の夜に𩸽食べたいがき console.log( '👨‍👩‍👧‍👦'.length, '🌕'.length, '𩸽'.length, str0.length, str1.length, str2.length ); // 11 2 2 11 13 14 // NG console.log(str1.split('').reverse().join('')); // きがいたべ食��に夜の�🁦�‍��‍��‍�� console.log(str2.split('').reverse().join('')); // ぎかいたべ食��に夜の�🁦�‍��‍��‍�� // NG console.log([...str1].reverse().join('')); // きがいたべ食𩸽に夜の🌕👦‍👧‍👩‍👨 console.log([...str2].reverse().join('')); // ぎかいたべ食𩸽に夜の🌕👦‍👧‍👩‍👨 // better console.log([...str1.normalize()].reverse().join('')); // きがいたべ食𩸽に夜の🌕👦‍👧‍👩‍👨 console.log([...str2.normalize()].reverse().join('')); // きがいたべ食𩸽に夜の🌕👦‍👧‍👩‍👨 // good console.log(split(str1).reverse().join('')); // きがいたべ食𩸽に夜の🌕👨‍👩‍👧 console.log(split(str2).reverse().join('')); // きがいたべ食𩸽に夜の🌕👨‍👩‍👧‍ 参考 文字列を1文字ずつ配列化(サロゲートペアを考慮) - Qiita https://qiita.com/sounisi5011/items/aa2d747322aad4850fe7 Unicode と JavaScript の文字列について - Object.create(null) https://susisu.hatenablog.com/entry/2017/01/25/023338 JavaScriptで絵文字とサロゲートペアと結合文字とgrapheme clusterを正しく扱うのに少し苦労した話 - Qiita https://qiita.com/amanoese/items/68bb9999829de4323302 文字とは何か?IchigoJam絵文字対応とUnicodeの旅、結合文字対応の文字分割ライブラリJavaScript対応版公開! #js #IchigoJam / 福野泰介の一日一創 / Create every day by Taisuke Fukuno https://fukuno.jig.jp/2831 JavaScript における文字コードと「文字数」の数え方 | blog.jxck.io https://blog.jxck.io/entries/2017-03-02/unicode-in-javascript.html
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScriptの基礎を改めて Part2

前回のPart1同様にJavaScriptの新たな気づきや重要だと感じた点をまとめる。 破壊的、非破壊的なメソッドについて 参照するデータに対して直接的な変更が入るメソッドは破壊的メソッドに分類される 。 例1 const array = ["A", "B", "C"]; console.log(array); >> ["A", "B", "C"]; const addedArray = array.push("D"); // pushメソッドは指定した配列に引数を加えるメソッド console.log(array); >> ["A", "B", "C", "D"]; // 配列arrayに直接的な変更が入っている。 対して参照するデータに対して直接的な変更が入らないメソッドは非破壊的メソッドに分類される。 例2 const array = ["A", "B", "C"]; console.log(array); const newArray = array.concat("D"); // concatメソッドは指定した配列をコピーしたものに引数を結合させるメソッド console.log(newArray); >> ["A", "B", "C", "D"] console.log(array); >> ["A", "B", "C"] // 配列arrayに対して直接的な変更が入っていない JavaScriptにおける破壊的、非破壊的メソッドはメソッド名から区別できず、破壊的メソッドは意図しない動作(副作用)が起こりうる。 そのため破壊的メソッドか否かは開発時点で引数にした配列に対してconsole.logメソッド等で確認する必要がある。 対策として破壊的メソッドでプログラムを記述した際は破壊的メソッドである旨を コメントアウトすることで問題発生時の切り分けを手助けするとよい。 例3 const removeIndex = (array, index) => { array.splice(index, 1); // spliceメソッドは配列arrayの指定したindexに対応したデータのみを削除した配列を返す return array; } const array = ["A", "B", "C"]; console.log(array); >> ["A", "B", "C"] // この時点では配列arrayにremoveIndex関数を実行していないためすべての要素が返ってくる。 const newArray = removeIndex(array, 1); // 変数newArrayにremoveIndex関数の実行結果を定義。 console.log(newArray); >> ["A","C"] // removeIndex関数によってarray[1]が削除されるconsole.log(array); >> ["A","C"] /* spliceメソッドは配列に対して破壊的な変更を加えるため、 removeIndex関数によって配列arrayにも影響を及ぼす。*/ もう一つの対策は破壊的メソッドの引数に予め非破壊的メソッドでコピーした配列を指定することである。 例4 const removeIndex = (array, index) => { array.splice(index, 1); return array; } const array = ["A", "B", "C"]; const copiedArray = array.concat(); // concatメソッドは引数なしだと指定した配列(今回ならarray)をコピーしてくれる。 console.log(array); >> ["A","B","C"] console.log(copiedArray); >> ["A","B","C"] const newArray = removeIndex(copiedArray, 1); // removeIndex関数の引数にconcatメソッドでコピーした配列を指定。 console.log(newArray); >> ["A","C"] // copiedArray[1]を削除した配列が返ってくる console.log(array); >> ["A","B","C"] // 配列arrayに対してはremoveIndex関数を実行していないため副作用なし。 メソッドチェーン 配列に対してメソッドを連続して行うこと。 メソッド毎に変数に対して結果を定義する手間を省くことができる。 例5 const array = [ { name: "Tanaka", age: 10 }, { name: "Suzuki", age: 12 }, { name: "Kobayashi", age: 20 }, { name: "Takeuchi", age: 33 }, ]; const sortAge = array .filter(data => data.age <= 15); // filterメソッドで配列array内のageが15以下のオブジェクトを抽出。 .map(data => data.name); // filterメソッドで抽出されたarrayに対してmapメソッドで指定したプロパティを取得。 console.log(sortAge); >> ["Tanaka", "Suzuki"] // ageが15以下のオブジェクトのnameを取得。 複数の処理をメソッドチェーンで一連の処理として記述することができるが、 記述が長くなりすぎると可読性が落ちるため適度な単位(段落)をメソッドチェーンで 記述することを意識する必要がある。 (処理1〜30 => 処理(1〜10)、処理(11〜20)、処理(21〜30)で区分けするイメージ)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

create-react-appは外部ディスクで実行してはいけないという戒め

Reactのローカル環境を構築して、いざアプリを作成しようとした際にエラーでハマった。 結論 create-react-appコマンドはローカルディスク上で実行しましょう。 エラー内容は以下。 $ npx create-react-app my-app Creating a new React app in /Users/XXX/Box/Programming/JavaScript/my-app. Installing packages. This might take a couple of minutes. Installing react, react-dom, and react-scripts with cra-template... npm ERR! cb() never called! npm ERR! This is an error with npm itself. Please report this error at: npm ERR! <https://github.com/npm/cli/issues> cb()という関数が呼ばれてないというエラーが発生している模様。 アタッチしているBOXドライブ上にあるフォルダ配下でアプリを作成しようとした結果、上記のエラーが発生した。 ローカルディレクトリのダウンロードフォルダ内で同様のコマンドを実行したところ問題なくアプリ作成ができたので、BOXドライブ上とローカルディレクトリ上で出来ることが違うっぽい・・・? BOXドライブはPCにアタッチされてるから特に問題なく使用できると思ったんだけど、そうではないらしい。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.js~v-for~

概要 JSでは、イベント(ユーザーがクリックしたときなど)に処理(イベントハンドラーと言います)が始まります。 その際に、クリックイベントを取得することにより実行することができました。Vue.jsでも記述は多少異なりますが仕組みは変わりません。 繰り返し処理についての記事です。 繰り返し処理 Vue.jsでは、繰り返し処理の際に[v-for]を使用します。 HTML index.html <ul> <li v-for="list in lists">{{ list }}</li> </ul> 構文は以下のようになります。 v-for="仮変数 in 任意の配列" 配列listsから順に要素を取り出します。 マスタッシュ構文に変数listを格納します。 このlistの中にlistsの配列の中身がなくなるまで繰り返し処理されます。 Vue index.js data:{ lists:[ 'list1', 'list2', 'list3' ] } index番号 インデックス番号を取得します。 index.html <ul> <li v-for="(list,i) in lists">{{ list + i }}</li> </ul> //list1 0 //list2 1 //list3 2 配列要素+インデックス番号で取得することが出来ます。 番外編for文 index.js <span v-for="i in 10">{{i }}</span> //12345678910
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Javascript  オブジェクト  私初心者なので 復習

オブジェクト 配列は要素を   [] で囲んだ オブジェクトは   {} で囲むよ { プロパティ1 : 値1, プロパティ2 : 値2}        ↑コロン ↑コンマ {name :"flower", price : 300} const item = {name: "flower", price: 300}; //定数名itemに↑を代入 console.log(item); //コンソール表示には {name: "flower", price: 300}と出る きゅうにオブジェクトの値が取り出したい衝動に駆られたら const item = {name: "flower",price:300}; console.log(item.name); //↑nameプロパティの値を取得 //コンソール表示には  flower とでます。 ```   :pencil2:きゅうにオブジェクトの値を更新したい衝動に駆られたら:point_left: ```javascript const item = {name: "flower",price:300}; item.price = 500;//値段を変える・更新 console.log(item.price); //コンソール表示には 500  ```  :pencil2:オブジェクト・配列・改行 配列は要素を   [] で囲んだ オブジェクトは   {} で囲むよ って学んだ オブジェクトを要素に持つ配列ができる [{プロパティ1:値1・・・},{プロパティ2:値2・・・}] →こんな形 ```javascript const item = [ {name: "flower",price:300}, {name: "ribbon",price:200} ]; // ↑コードが横に長くなるのを防ぐために、要素ごとに改行することがあるよ //配列の中のオブジェクトを取り出したい ・・・0から番号がつけられてたことを思い出して! const item = [ {name: "flower",price:300},//0番 {name: "ribbon",price:200}//1番 ]; console.log(item[1]); //コンソール表示には {name: "ribbon",price:200}と表示 //次は、配列の中の オブジェクトの値を取り出してみる const item = [ {name: "flower",price:300},//0番 {name: "ribbon",price:200}//1番 ]; console.log(item[1].price); //コンソール表示 200
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

タグ付きテンプレートでコーディングしてみるテスト

簡単なページを作る時にwikiのように書けたらと思い test.js $(e=>{ var vote = ` Across the Universe Baby It's You Carol Dear Prudence Every Little Thing `.trim().split(/\s*\n+\s*/) var episode = Object.entries({ EVENT_A:'All You Need Is Love', EVENT_B:'Bad Boy', EVENT_C:'Come Together', EVENT_D:'Dig a Pony', }) $('body').append(_html` ul.Tab( li,data-index=0,tab li,data-index=1,tab li,data-index=2,tab ),${e=>console.log(e.target.dataset)} .Contents( .pane,data-tab=Content1( .cover,image=hero.png,text .header,Content1 | header-1 .row(span,Ain't She Sweet) .row(b,Baby It's You) //.row(img,src=Telop.png) ) .pane,data-tab=Content2( .header,Content2 | header-1 ul.rows,${vote.map(s=>_html('li',s))} .header,Content2 | header-2 ul.rows,${vote.map((s,i)=> _html('li',s,{index:i,value:s}) )},${e=>{ console.log(e.target.dataset) }} ) .pane,data-tab=Content3( .header,Content3 | header-1 ul.rows,${episode.map(a=> _html('li,name:',a[1],{type:a[0],value:a[1]}) )},${e=>{ console.log(e.target.dataset) }} ) ) `) }) function _html(...a){ if(typeof a[0]==='string') return _html.static.create(a) if(a[0] instanceof jQuery) return _html.static.append(a.shift(),a) if(_html.template.isTagged(a)) return _html.template.parse(a) return $('<div>') } _html.static = new class{ video(){return $('<video loop autoplay muted>')} image(q,s){q.css('background-image',`url(${s})`)} data(q,data){$.each(data,(k,v)=>{q[0].dataset[k]=v})} create(a){ var q,m var text = a.shift().trim().replace(/\s*(,|=)\s*/g,'$1') switch(m = text.match(/^\w+/)){ case 'video': q = this.video(); break; case null: q = $('<div>'); break; default: q = $('<'+m+'>') } text.replace(/,([\w-]+)=([^,]+)/g,(m,k,v)=>{ switch(k.toLowerCase()){ case 'image': this.image(q,v); break; case 'background': this.image(q,v); break; default: q.attr(k,v) } return '' }).replace(/,([^,]+)/g,(m,s)=>{ q.append(s) return '' }).replace(/([#\.])([\w-]+)/g,(m,s,t)=>{ switch(s){ case '#': q.attr('id',t); break; case '.': q.addClass(t); break; } return '' }) return this.append(q,a) } append(q,a){ a.forEach(v=>{ if(v instanceof jQuery){ q.append(v) }else{ switch(Object.prototype.toString.call(v)){ case '[object Function]': q.click(v); break; case '[object Object]': this.data(q,v); break; default:q.append(v); } } }) return q } } _html.template = new class{ isTagged(a){ if(Array.isArray(a[0])==false) return false if(a[0].length!=a.length) return false if(a[0].hasOwnProperty('raw')==false) return false return true } parse(a){ var text = a[0].map((s,i)=>{ if(i==0) return s if(typeof a[i]==='string') return a[i]+s return '<!--'+i+'-->'+s }).join('').trim() var _check = text while (/\(([^()]+)\)/.test(text)){ text = text.replace(/\(([^()]*)\)/g,(m,s)=>{ a.push(this.rows(s.trim(),a)) return '<!--'+(a.length-1)+'-->' }) } var v = this.rows(text,a) if(v.length==1) return v[0] return _html('',v) } rows(text,vars){ var rows = text.trim().split(/\s*\n\s*/).map(row=>{ if(/<!--\d+-->/.test(row)) return this.row(row,vars) return [row] }).filter(a=>/^\/\//.test(a[0])==false) return rows.map(args=>_html(...args)) } row(row,vars){ var args = [] row.replace(/(<!--|-->)/g,m=>{ if(m=='<!--') return "\n"+m if(m=='-->') return m+"\n" return r }).split("\n").forEach((s,i)=>{ var m = s.match(/^<!--(\d+)-->$/) switch(true){ case(m!=null): args.push(vars[m[1]]); break case(i==0): args.push(s.replace(/,+$/,'')); break default: args = args.concat(s.split(',')); } }) args = args.filter(s=>s!='') if(typeof args[0] ==='string') return args if(args[0] instanceof jQuery) return args args.unshift('div') return args } }
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

for文の繰り返し処理(JavaScript)

Webページではある数値や数式、文字列を繰り返し用いるシーンは数多く見られますがその時に便利なのがJavaScriptでfor文を使ったループ(繰り返し)処理です。 用途に応じてfor文と while文 という2種類を使い分けます。 ここではfor文の繰り返し処理の基礎を説明していきます。 for文 for文は繰り返す回数が決まっている場合に使用します。 式は以下の通りです。 for (初期値; 条件式; 増減式) {   繰り返し処理 } 参考例を使って実際に動かしてみましょう。 for (var i = 0; i < 5; i++) { console.log(i + "←iが1ずつ上がっていきます"); } こちらをコンソールで見てみると 0←iが1ずつ上がっていきます test.js:2 1←iが1ずつ上がっていきます test.js:2 2←iが1ずつ上がっていきます test.js:2 3←iが1ずつ上がっていきます test.js:2 4←iが1ずつ上がっていきます このようになります! 初期値 var i = 0;  「i」という変数を定義して、0を代入しています。 条件式 i < 5;   i < 5がtrueの場合に処理を繰り返すことを意味しています。 増減式 i++  処理を繰り返すたびに i に1を足していくことを意味しています。  (i++は1ずつ足していく、i–は1ずつ減らしていく、という意味) つまり 4←iが1ずつ上がっていくのですが出力された後は「i」の値が 5になります。 その場合条件式が 5 < 5になり、falseが返るため、繰り返し処理をしないということです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Vue.js出力

概要 Vue.jsでこんにちわを出力するまでについて、まとめました。 HTML index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="css/styl.css"> <title>Document</title> </head> <body> <div id="app"> <p>皆さん{{ message }}</p> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script> <script src="js/main.js"></script> </body> </html> Vue.jsは、HTMLのテンプレート構文があります。 今回の実装ではHTMLファイルを使用します。 Vue.jsの機能を適用させるためにbody要素の直下にdiv要素を作ります。id属性を使用します。名前は特に決まりはありません。 JS側で、このidをターゲットにVue.jsが提供するデータや、メソッドを使用します。 このidターゲットがない場合、Vue.jsを使用することが出来ません。 {{...}}これをマスタッシュ構文と言います。これを書くことで、dataオブジェクトのmesaggeプロパティの値を引用することが出来ます。 scriptタグには、Vue本体のCDNを組み込みます。ローカル環境にダウンロードしたVue本体のファイルを読み込み、ユーザーが作成したファイルを実行する方法です。 2つ目のscriptタグにJSファイルを読み込みます。 *注意:2つのスクリプトタグを反対に記述すると、CDNが読み込まれる前にJSファイルが読み込まれてしい、errorになります。 JS index.js const app =new Vue({ el:'#app', data:{ message:'こんにちわ' } }); Vue.jsは、Vueクラスをインスタンス化して使用します。 new Vueは、Vueクラスからインスタンスを生成する場合の命令です。 {}の中には、オブジェクトリテラルを書きます。 el ▶Vueインスタンスを結びつけるHTML要素を指定します。 data▶Vue.jsで扱うデータを入れておく場所です。 このデータをHTMLファイルから読み込み画面に表示することが出来ます。テンプレートHTMLから参照できる値を参照できる値を格納したオブジェクトです。なお、マスタッシュ構文に格納できるのは式だけです。代入、条件分岐は使用することは出来ません。 Vue.jsでは、アプリを利用する値をデータオブジェクトで用意して、テンプレートが参照することをデータバインディングと言います。 {マスタッシュ構文}では属性の値などは指定することは出来ません。 属性の変更、条件分岐などはディレクティブを使用します。ディレクティブは[v-]から始まります。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Javascript  配列  私初心者なので 復習

複数の数値をまとめる const fruit1 = "apple"; const fruit2 = "grape"; const fruit3 = "banana"; どうにか・・・この3つひとつにまとまんないかな まとめて書きたい場合には、配列を使うよ 文字列をまとめた配列 ["apple","grape","banana"]  ↑要素という その後(,)コンマで区切るよ 数値をまとめたらこんな感じ [12,17,41] もうちょいレベルアップ!配列を定数に代入する 配列も一つの値なので、定数に代入することができます。 const fruits = ["apple","grape","banana"]; ↑定数名   ↑定数名に代入されるよ console.log(fruits); コンソールの表示には ["apple","grape","banana"] が表示されるよ 0から始まるインデックス番号 配列には番号がついている!なんと! そうなのか・・・ ["apple","grape","banana"]  ↑0    ↑1    ↑2 じゃあこの番号を使って、要素を取得してみる const fruits = ["apple","grape","banana"]; console.log(fruits[0]);//appleの番号 console.log(fruits[2]);//bananaの番号 //コンソールの表示は apple banana と出るよ さらに配列の要素を上書きすることもできるんだって const fruits = ["apple","grape","banana"]; console.log(fruits[0]); //ここまではいい fruits[0] = "melon";//!!!!!!!!!!!!!!0のところ更新!つか上書きです。 console.log(fruits[0]); //コンソールには、最初の値 apple //次に聞かれた値     melonが表示されるよ 配列に対しても繰り返しが使える???????????????????for文? const fruits = ["apple","grape","banana"]; console.log(fruits[0]); console.log(fruits[1]); console.log(fruits[2]);//この3つをfor文に置き換えることができるよ const fruits = ["apple","grape","banana"]; for (let i = 0; i < 3; i++){ //iが0〜2の間をループする console.log(fruits[i]);//変数iを使って要素を取得 } メモ let変数    const定数 配列と繰り返し length 要素の数だします係 めっちゃ使えるやつみたいです。 const fruits = ["apple","grape","banana"]; console.log(fruits.length); ↑ドットで繋げる! コンソールの表示は 3と出る。 const fruits = ["apple","grape","banana"]; for(let i =0; i < fruits.length; i++){ //lengthを用いて書き換えることができる console.log(fruits[i]); }    
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScriptのフレームワーク

概要 JSのライブラリとフレームワークについて触れます。 1,フレームワークとライブラリについての違いについて 2,JSのフレームワーク 3,Vue.jsの特徴 3,コンポーネント指向とは 1,フレームワークとは 本来、開発する上で必ずフレームワークが必要な訳ではありません。JSだけでアプリ開発を行うことはできます。 しかし、大規模な開発を大人数ですすめているとします。そして、コードの書き方が人により少しずつ変わっているとします。 このように、書き方が少しずつ違うコードを複数人で着手するのはバグに繋がります。そこで、必要になるのがフレームワークです。 フレームワークとは、再利用可能なクラスを言います。設計・開発でよく使用するコードをフレームワークが用意してくれています。 プログラマーは、フレームワークが提供してくれる枠組みにそって開発することが出来ます。 それにより、バグが少ない設計になりより堅牢なアプリケーションとして開発することが出来ます。 ただし、現段階であまり複雑な設計で無いならば無理にフレームワークを導入する必要はありません。 ライブラリとは ライブラリとは、コードをより簡略的に記述することが出来ます。JSで記述する長いコードをjQueryを使用することで、より簡略的に書くことが出来ます。それにより、動作を軽くすることが出来ます。 ライブラリとはユーザーが呼び出して複数回記述するコードを効率的に記述し、開発をすすめることを目的としています。 フレームワークとはすでに用意されている骨組みを再利用して効率的に開発をすすめることを目的としています。 2,JSのフレームワーク Angula ▶グーグルを中心に開発されているフルスタックフレームワーク React ▶フェイスブックが開発したビュー相当の機能を提供するフレームワーク Vue ▶ ビューに特化したシンプルなフレームワーク 3,Vue.jsの特徴 1,コストが低い Vue.jsは、HTMLベースのテンプレート構文を採用しています。なので、初心者にも学習コストが低いと言われています。 2,段階的に導入することができる 例えば、規模を小さく提供したアプリケーションが拡大したため機能を追加する必要が出てきたとします。その場合に、段階にあわせてシステムを導入しやすいというメリットがあります。 アプリが大規模になり、似たようなUIが出てきたら、コンポーネントを導入することが出来ます。 また、機能が増えて明確にURLを分割することが出来ます。VueRouterを使用することが出来ます。 アプリで扱うグローバルなデータを中央管理するためのデータベースが必要になってきます。そこで使用するのが、Vuexです。 4,コンポーネント指向 コンポーネントとはアプリを構成するUIの部分です。テンプレート、オブジェクト、スタイルの集合体です。 ある程度、規模が大きくなるとコンポーネントを組み合わせて作リます。 コンポーネントは、複数配置することも出来ます。また入れ子にすることも出来ます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ウルトラ簡単に導入できてしまうBootstrap

こんにちは。 当記事ではBootstrap導入と簡単な使用例について記していきます。 対象はプログラミングhtmlやcssは触ったことある初学者向けです。 ※検証環境:Eclipse・GoogleChrome(Java8・PostgreSQL・SpringBoot・Thymeleaf) 1.以下サイトからBootstrap本体をダウンロード https://getbootstrap.com/docs/5.0/getting-started/download/ 2.ダウンロードしたzipを解凍後cssとjsファイルを自分の環境にコピーする。 私の開発環境のSpringbootアプリだとここにドラッグ&ドロップしました。 3.HTMLファイルに以下を追記する 3.1 <head></head>の中に以下2行をコピー sample.html <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> 3.2 <body></body>の中に以下3行をコピー(私はbody部の最後に書きました) sample.html <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> BootStrapの導入は以上で終わりです。pomに追記するなどの別の方法もありますが、今回は割愛します。 後は実際にHTMLのタグにclassを追加して試してみると良いと思われます。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ヒストグラムの作成

今回はJavaScriptを用いて100人分のテストの点数をヒストグラムにして表すということをやっていきます //以下のfor分で100人分のテストの結果を作成 //0.5.点以上100.5点未満の乱数を作成(Math.random()*100)+0.5 //これを切り下げる(Math.floor)ことで0以上100以下の結果が出る // const scoreMake=[]; // for (i=0; i<100 ; i++){ // score.push(Math.floor((Math.random()*100)+0.5)) // } // console.log(scoreMake); const score = [ 46, 20, 18, 49, 94, 86, 71, 20, 21, 24, 25, 31, 89, 10, 54, 27, 41, 63, 9, 96, 16, 42, 71, 79, 77, 1, 24, 72, 84, 43, 94, 42, 59, 2, 16, 10, 63, 89, 41, 74, 59, 17, 41, 74, 86, 19, 30, 65, 11, 28, 66, 35, 20, 3, 6, 78, 21, 38, 36, 43, 30, 33, 13, 19, 46, 17, 69, 87, 46, 43, 91, 12, 97, 82, 62, 30, 31, 96, 73, 3, 56, 51, 43, 21, 41, 7, 74, 100, 83, 54, 17, 21, 81, 30, 79, 25, 22, 73, 42, 81, ]; // const count=[0点台,10点台,...,100点台]各要素10点ごとに何人いるか表すために作成 const count = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; for (i = 0; i < 100; i++) { //点数の10の位に注目して10の位だけを表す const num = Math.floor(score[i] / 10); //各要素に追加 count[num]++; } // console.log(count) // [(7, 13, 14, 10, 15, 6, 6, 12, 10, 6, 1)]; //何点台の人数が最も多いか取ってくる const max = Math.max.apply(null,count); //ヒストグラムの作成 for (i = 0; i < max; i++) { const array = []; for (j = 0; j < count.length; j++) { if (max - i <= count[j]) { array.push("*"); } else { array.push(" "); } } array.join("") console.log(array.join(" ")); } console.log("--------------------------------") console.log("0 10 20 30 40 50 60 70 80 90 100") // * // * * // * * * // * * * * // * * * * // * * * * * * // * * * * * * // * * * * * * // * * * * * * * // * * * * * * * * * * // * * * * * * * * * * // * * * * * * * * * * // * * * * * * * * * * // * * * * * * * * * * // * * * * * * * * * * * // -------------------------------- // 0 10 20 30 40 50 60 70 80 90 100
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

JavaScript 変数名と値を文字列として取得する

JavaScriptじゃない記事ですが次の記事を見ました。 デバッグ時はprintではなく、Icecreamを使うと便利 - Qiita https://qiita.com/purun/items/c7aca300b970344214cf JavaScript でも、変数名と値を同時出力したいと以前から思っていました。 const a = 10; console.log(`a:${a}`); // a:10 開発時にデバッグログとして、こんな感じに出力するコード書くときがよくあります。 この時、変数名が1文字とかなら問題ないですが、きれいなコードを書こうとするとぼちぼち変数名は長くなる時は多くあります。その時に、変数名を2回書くのがだるいわけです。 なので、どうにか解決したいかなと思って、次の関数を書いてみました。evalを使えばできます。 const varNameValue = (name) => { return `${name}:${eval(name)}`; } const a = 10; console.log(varNameValue('a')); // "a:10" これは確かにできるのですが、eval は、いろいろセキュリティとか考える必要があったりなかったりしそうでやっかいそうなので使うのを避けたいところ。 MDNでも酷評されている感じですし、いろいろ怖いです。使い方に注意しておけばそれほど問題ないとも思いますけれども、念の為なるべくevalは避けたい。 eval() を使わないでください! - eval() - JavaScript | MDN https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/eval#never_use_eval! MDNでは、eval の回避方法として、Function 使え、とあるけれども、今回の場合には当てはめられそうにないです。 どういうときってどうしたら効果的かコード書けるかな、と思ってたところに、タイムリーに、mizdra's blog で紹介されていました。 JavaScript で print デバッグ時に変数名を出力する - mizdra's blog https://www.mizdra.net/entry/2021/05/03/000139 簡単なのはこういうことなんですね。 console.log({a}); なるほど。オブジェクト生成の省略記法でオブジェクトをconsole.logに渡せば、ブラウザ側で変数展開してくれるか。 なるほどなるほど。 オブジェクトの省略記法を使えば、自分で変数名と値を展開して文字列として取得できるよな。そういえば。 ということで、ヒントにさせていただいて気がつけましたので、console.logにわたす前に変数名と値を展開して文字列として取得するにはこういうことすればいいなとわかりました。 const varNameValues = (args) => { const result = []; for (const [key, value] of Object.entries(args)) { result.push(`${key}:${value}`) } return result; } const a = 10; console.log(varNameValues({a})); // ["a:10"] const b = 20; console.log(varNameValues({a, b})); // ["a:10", "b:20"] これで、変数名と値とを同時に文字列取得し出力することができました。console.logだけじゃなくて独自ログとか、localstorageに保持とかもわかりやすいかもしれません。 mizdra's blog にすごく感謝です。ありがとうございます。 追記 varNameValues なんての作らなくても、こっちの方がいいかも。逆変換もできるし。 const a = 10; const b = 20; console.log(JSON.stringify({a,b})) // {"a":10,"b":20}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cloud Foundry(IBM Cloud)でNode.jsのバージョン指定【.nvmrc】

Node.jsアプリケーションをそのままデプロイしようとすると以下の警告が出ます。 **WARNING** Node version not specified in package.json or .nvmrc. See: http://docs.cloudfoundry.org/buildpacks/node/node-tips.html Attempting to install: 10.24.0 package.jsonか.nvmrcに記述しろと書いてありますね。 Support .nvmrc file as an alternative to engine.version setting in package.json 前に書いた記事ではpackage.jsonのenginesに記載するやり方でしたが、今回は.nvmrcに記述します。 Cloud Foundry(IBM Cloud)でNode.jsの最新バージョンを利用する .nvmrcを作成してデプロイ 今更ですがnvmを内部で使ってたんですね。 macなどの場合はプロジェクトのルートで以下を実行します。 $ node -v >> .nvmrc これで.nvmrcが作成されてローカルのバージョンが.nvmrcに記載されます。 ただ最新は動かない場合が多い 先程のコマンドを実施した.nvmrcの中身はv16.0.0でした。 v16.0.0 この状態でデプロイしたら以下のエラーが発生 **ERROR** Unable to install node: no match found for 16.0.0 in [10.23.3 10.24.0 12.20.2 12.21.0 14.15.5 14.16.0 15.11.0 15.12.0] 2021-05-04T02:26:19.14+0900 [STG/0] ERR Failed to compile droplet: Failed to run all supply scripts: exit status 14 まぁつまりv15.12.0までしか対応してないよとのことです。 v15.12.0 と変更してデプロイしなおすとエラー回避できます。 時期によって対応状況は違うので、まずは最新版でデプロイして出たエラーメッセージにどのバージョンで対応済みかを知るのが良いかもしれません。 最新を使いたい時はbuildpacks指定の方法も Cloud Foundry(IBM Cloud)でNode.jsの最新バージョンを利用するの記事にあるbuildpacksでURL指定などをすると最新が使えるかもしれません。 所感 package.jsonのenginesに指定していると他の環境で利用しようとした時や利用パッケージによって変な挙動が発生することがあるので、pacakge.jsonのenginesに指定よりは楽な印象です。 個人的に今後も触ることがあれば.nvmrcに記載の方を選ぶ気がします。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Cloud Foundry(IBM Cloud)にDiscord BOTをデプロイしようとした際にハマったメモ

手元で作成したDiscord BOTのNode.jsアプリケーションをCloud Foundry(IBM Cloud)にデプロイする際にハマりました。 デプロイ時間長すぎて検証に時間かかるのが大変...... おさらい: ログの調べ方 デプロイや起動に失敗した際は $ ibmcloud cf logs アプリ名 --recent でエラーログを見れます。 ERR Failed to make TCP connection to port 8080: デプロイ時後の起動時にエラーが発生してました。 2021-05-04T02:37:11.28+0900 [HEALTH/0] ERR Failed to make TCP connection to port 8080: connection refused (out of memory) 2021-05-04T02:37:11.28+0900 [CELL/0] ERR Failed after 1m0.927s: readiness health check never passed. 待ち受けるサーバーが無いよと怒られてる模様です。 Discord.jsを利用してますが、このライブラリはHTTP サーバーを立てる方式ではない模様です。 Discord.js does not expose any kind of port nor a http server. 参考: https://github.com/discordjs/discord.js/issues/3577 以下のようなDiscrod.jsのサンプルのままだとうまく起動してくれませんでした。 const Discord = require('discord.js'); const client = new Discord.Client(); client.on('ready', () => { console.log(`Logged in as ${client.user.tag}!`); }); client.on('message', async msg => { if (msg.content === 'ping') { msg.reply('Pong!'); } }); client.login(process.env.DISCORD_TOKEN); ちなみにこのときのmanifest.yamlはこんな感じです。 manifest.yaml applications: - name: アプリ名 random-route: true memory: 64M command: npm start 解決策1: expressを追加してサーバーを起動 待ち受けるサーバーが無くて怒られてるのでexpressを追加します。 const Discord = require('discord.js'); const client = new Discord.Client(); client.on('ready', () => { console.log(`Logged in as ${client.user.tag}!`); }); client.on('message', async msg => { if (msg.content === 'ping') { msg.reply('Pong!'); } }); client.login(process.env.DISCORD_TOKEN); /*expressを追加*/ const express = require('express') const app = express() app.get('/', function (req, res) { res.send('Hello World') }) app.listen(process.env.PORT || 3000); これでOKです。 解決策2: manifest.yaml(の変更でできる気がする) ProcessのTypeがWebでは無く別の指定にしたり、no-route: trueなども試してサーバーを追加しなくても起動するようにしたかったけどエラー解消されなかったです汗  参考: https://docs.cloudfoundry.org/devguide/deploy-apps/manifest-attributes.html 一旦諦め。 ERR Killed こちらもアプリ起動後に発生したエラーです。 [2021-05-04T10:52:45.49+0900 [APP/PROC/WEB/0] ERR Killed 例えば、 OOM Killed とあれば「メモリー不足」を意味し、コンテナーがリソース制限によってクラッシュしている 参考: https://www.ibm.com/docs/ja/bluemix_stage/containers/cs_troubleshoot_clusters.html?view=kc みたいな話をググったら見つけたので64Mに指定してメモリを128Mにしてみました。 manifest.yaml applications: - name: アプリ名 random-route: true memory: 128M command: npm start たまたま感ありますがこれで解決出来ました。 express入れた分でメモリ多く使ってしまったのかもしれません。 ひとりごと。 デプロイの時間が長すぎる問題 Cloud Foundryのmanifest.yamlだけでどうにかなる気がしてますが、検証しようにもデプロイの時間が長すぎる問題があります。 デプロイボタン押したらモンハンで一狩り行ってました。それくらい遅い。 ちゃちゃっと試したいのに時間長すぎるので拘りなければHerokuがいい気がするなぁ。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ルンゲクッタ法(四次)を実装(JavaScript)

ルンゲクッタ法とは ルンゲクッタ法は、常微分方程式において、解析的に解を求められない状況で初期値を元に適切な答えを求めるための数値解析手法. $$\frac{dy}{dx} = f(y,x)$$ 上記常微分方程式と適切な初期値が与えられる時にその解を数値計算で求めます. 今回は4次のルンゲクッタのJavaScript実装を行います. 参考文献に記載させていただいた神戸大学の陰山様の資料やYouTubeがイメージを掴むのによいかと思います. 次数に関しては、これも参考文献のシキノート様のが非常に参考になるかと思います. ルンゲクッタ実装 想定する関数は下記とします. $$y = \frac{1}{10} cos(x) + 3.9$$ 常微分方程式は以下とします. $$\frac{dy}{dx} = f(x) = -\frac{1}{10} sin(x)$$ y不使用のため、diffEquationでは、xしか引数に取っていません. 初期値は$(x,y)=(0, 4)$. rungeFに推定した関数の結果が入ります. const COEFF = 0.1; const DATA_NUM = 100; const HALF_DATA_NUM = Math.floor(DATA_NUM/2); const RUNGE_STEP = 0.1; let init_x = 0; let init_y = 4; let X = []; let datas = []; for(let i = 0; i < DATA_NUM; i++){ X.push((i - HALF_DATA_NUM) * COEFF); } function ansEquation(x){ return 1/10 * Math.cos(x) + 3.9; } function diffEquation(x){ return -1/10 * Math.sin(x); } let ansY = X.map((x)=> ansEquation(x)); let ansF = X.map(function(x,index){return {x:x, y:ansY[index]}}); let maxX = Math.max(...X); let curX = init_x; let prevY = init_y; let rungeF = [{x:curX, y:init_y}]; while(maxX > curX){ let k1 = diffEquation(curX); let k2 = diffEquation(curX + RUNGE_STEP / 2 * k1); let k3 = diffEquation(curX + RUNGE_STEP / 2 * k2); let k4 = diffEquation(curX + RUNGE_STEP * k3); let y = prevY + RUNGE_STEP * ( k1 * 1/6 + k2 * 2/6 + k3 * 2/6 + k4 * 1/6 ); curX += RUNGE_STEP; rungeF.push({x:curX, y:y}); prevY = y; } 参考文献
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

javascript 関数オブジェクトの内部関数へのアクセス(私的整理)

JSの関数オブジェクトは色々と生成方法があって、生成方法にって中身が異なったりするよう。すごく迷うところに感じる。 以下はちょっと自分的な迷いどころで、内部関数に関して自分用に整理してみた。 関数の生成 内部関数inn()へのアクセス 呼び出し 備考 sam=function( ){inn=function( ){ }}; 不可 - クロージャー function sam( ){inn=function( ){ }} 不可 - クロージャー sam=function( ){inn=function( ){ };return inn;}; 可 sam( )( ); 直接inn( )は呼べないが、returnで戻せばOK function sam( ){inn=function( ){ };return inn;} 可 sam( )( ); 上に同じ function sam( ){this.inn=function( ){ }} 可 new sam( ).inn( ); sam={inn:function( ){ }}; 可 sam.fun( ) innは関数ではなくパラメータ(クロージャーにならない) sam=function( ){inn.function( ){ }}には、constructorはなく、インスタンス化できないので、new sam( ).inn( );のようにはできない。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む