20211129のJavaScriptに関する記事は26件です。

Vanilla JavaScript をずっと書いていたけど、Reactに入門してみた。

はじめに お疲れさまです。急に寒い日々が続いていますが、皆様はいかがお過ごしでしょうか? 半年間、業務量が倍になり、なかなか技術本を読む時間が取れなかったです。。 しかし、最近は落ち着いたので、本を読む時間が取れそうです。。!(あとゲームも) Reactを勉強することにしました。 素のJavaScript(かろうじて、ES2015の記法を習得)に書き慣れているのですが、 本腰を入れて有名なフレームワーク Reactを勉強してみることにしました。 今回は環境構築を中心に備忘録として投稿します。 Windows11 Visual Studio Code Node.js Reactの開発環境を整える。 vscodeを開き、新しいフォルダーを作成します。 cmdを起動し、以下のコマンドを入力します。(sampleは任意のフォルダ名になります。) npx react-create-app sample ローカル環境でReactを起動してみます。 cd sample #プロジェクトに移動 npm start #start コマンドを実行する 下のように、表示されると、環境構築成功です。 Hello World!を表示してみる。 せっかくなんで、Hello world!をしてみましょう。 現在のフォルダ構成は以下の状態になっていると思いますが、 srcフォルダ内のindex.js以外のファイルを削除してください。 sample ├─node_modulues ├─public └─src index.jsを以下のように変更しましょう index.jsx import React from 'react'; import ReactDOM from 'react-dom'; const App = () => { return( <> <h1>Hello World!</h1> </> ); }; ReactDOM.render(<App />, document.getElementById('root'); 下のように表示されましたでしょうか? 所感 今回は、Reactの環境構築とHello Worldの表示を行いました。 index.jsで少しだけ登場したJSX記法。。最初は、違和感ありましたが、 書いてみるとなかなか、面白いですね。 今回はh1タグ一つだけですが、これを関数コンポーネントを利用して画面の一つ一つを部品として とらえて、描画していきます。 終わりに 1回目の投稿で、Pythonを使った自動翻訳を紹介しました。 (動かないコードを公開する大失態をしでかしてますが。。) 2回目でReactの環境構築を紹介して、何をしてるんだと思います。 。。実は、Pythonの自動翻訳ですが、結構注文が来てます。「このファイル翻訳してください」と。 需要があるなら展開しようと考えたのですが、どうせならGUIで操作できるようにしたいな~と それなら、フロントエンドをReactで作ってみよう!と現在学習中です。 Webサーバーの環境はないので、デスクトップアプリとして展開するのですが、 Python寄りでEelを使用するか、JavaScript寄りでElectronを使用するか。ですね。 そこまで、急ぎの案件ではなく、業務改善の一環で行っていることですので、 手堅く作るならElectronでしょうか? EelとElectronも環境構築できる程度は学習しましたので、これらも投稿できればいいかなと 思っています。 長文になりましたが、Reactに入門してみました。 ここまで読んで頂いた方、ありがとうございました。 次の投稿は。。来年かな?
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

電卓の成長を体験できるクソアプリ

クソアプリ Advent Calendar 2021 1日目の記事です。 前置き おはようございます。DE-TEIUです。 クソアプリを開発しないと年を越せない体になってしまったので今年もやっていきます。 過去にアドベントカレンダー用に作ったクソアプリ p5.jsで作ったダメなソリティア 絶対に作業できない作業用BGMサイト 社会に一石を投じるクソアプリ開発 鼻毛が生えるカメラアプリ 映画館のスクリーンでYouTubeが見られるクソアプリ 成果物 誰しも人生の中で一度は電卓に触れる機会があったと思います。 しかし、実は皆様の知る電卓というのは、既にレベルが最大まで上がって完成されているものだったのです。 というわけで、今回は電卓が成長していく過程を体験できるWebアプリを開発しました。 適当にボタンを押したり計算したりすると経験値が溜まって電卓のレベルが上がっていきます。 電卓育成シミュレーター 電卓のレベルが 上がったと思います。最大レベルは15です。 解説 以下、今回使用したフレームワークとライブラリの紹介です。 Svelte bignumber.js Svelte Svelteとは、ReactやVueのようなJavaScriptフレームワークの一種です。スヴェルトと読むそうです。より少ないコード量で実装できることを売りにしており、かなり直感的に書けるように設計されています。 サンプル 例えば、2つの入力欄に設定した値を合算する機能を実装すると以下のようになります。 sample.svelte <script> let val1 = 0; let val2 = 0; </script> <input type="number" bind:value={val1}> <input type="number" bind:value={val2}> <p>{val1 + val2}</p> 同じものをVueで実装するとこうなります。 sample.vue <template> <div> <input type="number" v-model.number="val1"> <input type="number" v-model.number="val2"> <p>{{val1 + val2}}</p> </div> </template> <script> export default { data: function() { return { val1: 0, val2: 0, }; } }; </script> 上記の2つのコードを比較すると、Svelteでは、バインドさせたい変数の宣言が、普通のJavaScriptと同じようにletやconstで書けるようになっています。 Svelteフレームワーク 今回のアプリでは使用していませんが、ReactにおけるNext.jsや、VueにおけるNuxt.jsのように、Svelteにも本格的なWebアプリを開発するための機能が色々と追加された、SvelteKitというフレームワークが存在します。Svelteには元々Sapperというフレームワークが存在していたのですが、現在はこれの開発を中断され、SvelteKitの開発が進められています。 2021/12/01時点ではまだSvelteKitはβ版であり、まだNext.jsやNuxt.jsよりは機能やドキュメントが少なかったりするので、作りたいシステムの要件によっては採用が難しいかもしれません。ただ通常のSvelteと同様に、SvelteKitもかなりシンプルな書き方で実装できるようになっているため、個人で小規模なWebアプリを作るぐらいなら問題なく使えるかと思います。 bignumber.js JavaScriptでは、数値計算(特に小数を含んだもの)の際、しばしば誤差が発生します。 例: JavaScriptの浮動小数点数は IEEE754 という規格に則って実装されているため、この規格について調べると更に詳しい情報が得られるかと思います。今回の記事では割愛します。 この誤差の発生を防ぐような計算処理を自前で実装するのは大変なので、今回はbignumber.jsというライブラリを使用しました。 なんとなくJavaのBigDecimal型っぽい使い方ができますね。 インストール $ npm install bignumber.js 使い方例 import { BigNumber } from "bignumber.js"; const num = new BigNumber(0.1); // 加算 const val1 = num.plus(0.2); // 減算 const val2 = num.minus(0.2); // 乗算 const val3 = num.multipliedBy(0.2); //除算 const val4 = num.dividedBy(0.2); // 計算結果を文字列化して出力 console.log(val1.toString(), val2.toString(), val3.toString(), val4.toString()); // カンマ区切りで出力 const val5 = new BigNumber(1000000); console.log(val5.toFormat()); 出力例 0.3 -0.1 0.02 0.5 1,000,000 他にも、大小比較や、小数の丸め処理の設定ができたりします。詳しくはAPI参照。 まとめ 普通に完成された電卓を使った方が良いですね。 参考 Svelte • Cybernetically enhanced web apps bignumber.js API JavaScriptで小数点の誤差が発生する件の備忘録 - Qiita WEB+DB PRESS Vol.122
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Electronの始め方〜HelloWorldまで〜

普段はElectronとは無縁の生活の者です。 2018年くらいの記事を読んで失敗したので書き留めます。 今回はElectronでhello worldできれば完成です! ディレクトリ作成 mkdir helloworld ファイルの追加 次にhelloworldディレクトリに3つファイルを追加します。 helloworld/  ├ main.js  ├ preload.js  └ index.html main.js const { app, BrowserWindow } = require('electron') const path = require('path') function createWindow () { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__dirname, 'preload.js') } }) win.loadFile('index.html') } app.whenReady().then(() => { createWindow() app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow() } }) }) app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } }) preload.js window.addEventListener('DOMContentLoaded', () => { const replaceText = (selector, text) => { const element = document.getElementById(selector) if (element) element.innerText = text } for (const type of ['chrome', 'node', 'electron']) { replaceText(`${type}-version`, process.versions[type]) } }) index.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Hello World!</title> <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" /> </head> <body> <h1>Hello World!</h1> </body> npmのインストール cd helloworld npm init package.jsonを編集します。 package.json { "name": "helloworld", "version": "1.0.0", "description": "", "main": "main.js", "dependencies": { "electron": "^16.0.2" }, "devDependencies": {}, "scripts": { "start": "electron .", "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" } ここで注意する点は、 "main"の部分が"main.js"になっているか。 それと、 "script"の部分に"start"の部分を足すこと。 次に、やっとelectronのインストールに入ります。 npm install --save-dev electron helloworldディレクトリでインストールします。当たり前だけど、間違えがち。変なディレクトリでインストールしがち。 これでOK 起動します。もちろんhelloworldディレクトリで。 npm start めでたくhelloworld!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Denoに今後導入される新機能(2021秋ver)

リリーススケジュール 2021年10月12日: Deno1.15のリリース 2021年11月16日: Deno1.16のリリース 2021年12月16日: Deno1.17のリリース [TypeScript4.5] 2022年1月20日: Deno1.18のリリース 2022年2月17日: Deno1.19のリリース Denoのリリーススケジュールは基本的にv8のアップデート周期(4週間)と一致するようになっています。 11月に予定されていたDeno2.0は、来年に延期されました。 Denoに今後導入される新機能 前回の記事から大分間が空いてしまいました… 以下に挙げるのは、導入される方向で議論が進んでいるものです。タイトルでは秋verと銘打ってはいるものの、進捗状況次第では導入が来年以降に持ち越されることもあり得ます。 また、ここで取り上げるのはほんの一部です。詳しい変更内容は各リリースのリリースノートを参照してください。 Node.js互換モード denoにNode.js互換モードが導入されます。 これまで、Node.js向けライブラリの類はesm.shなどの3rd party CDNを利用することで、Denoからも利用できました。しかし、アプリケーション(サーバー等、ライブラリを使う側のコード)はDenoへの移行手段がありませんでした。Node.js互換モードは、こうした既存のコードベースをDenoに移行するための手段として開発されています。 Node.js互換モードを使うには、実行時に--compatフラグを設定することで使用できます。 > deno run --compat --unstable ./main.ts まだ実験的な扱いであり、--unsableフラグも必要です。 フラグ下では、require、node_modulesとpackage.jsonのサポート、node組み込みライブラリのpolyfillの差し込みなどが行われます。 今のところpolyfillが途中なため、一部のモジュールのみ動作します。現時点ではESLintやExpressが動くようになったという状況で、今後はvite、MongoDBドライバー、Mocha、Next.jsなどが動くことを目指してpolyfillを進めていくようです。 この機能はあくまでNode.jsからの移行のためであり、新しいプロジェクトを互換モードで開始する必要はなく、(エコシステム上)移行が十分に進んだら互換モードを削除する方針とのこと。 関連:#12108、#12295、#12577 deno deployの正式提供 Deno Deployは、JavaScript、TypeScript、および WebAssembly を世界中のエッジで実行する分散システムです 。 以下のような特徴があります。 例えばCloudFront Functionsがリダイレクト等の軽い処理を実行時間制限付きで行うのに対し、deno deployはメインのアプリケーションを全てエッジで実行する deno CLIで利用できるAPIと互換性があり、ローカル開発をDeno CLIで行うことができる GitHub連携を行うとGitHubリポジトリのファイルをローカルファイルのように扱うことができる サーバーの負荷に応じてサーバーが複数建ち、並列でリクエストを捌くことができる 日本では、東京リージョンと大阪リージョンが存在 playgroundがある https://dash.deno.com/playground/my-server-example 現在ベータリリース中(正式提供は2021年第4四半期に予定) 今後のアップデートでは、正式リリースに向けてキャッシュ機能が追加される予定です。 また、CLIとの相互運用性、より良い開始フローにも対応していくとのこと。 deno deployのissueレポート用リポジトリによると、長期的には、定期実行やストレージなどのサポートも検討されているようです。 TypeScript 4.5 Deno1.17にてTypeScript4.5が導入されます。 TypeScript4.5によって、以下の機能が利用可能になります。 インポートアサーション プライベートフィールドの人間工学的ブランドチェック(#foo in obj構文) .mts .ctsのサポート Awaitedユーティリティ型 …他 詳しくはTS4.5のリリースノートを参照してください。 また、TSがインポートアサーションに対応する事によって、DenoにJSONインポートのサポートが追加されます。 deno.jsonの強化 deno.json(deno設定ファイル)にはフォーマッタやリンターの設定、TSのcompilerOptionを書くことができます。将来的にこれを拡張して、import-map、--allowフラグ、タスクランナーを設定できるようにすることが検討されています。 現在検討されている構文は以下のようなものです。 deno.jsonc // 当該issueから引用 { "compilerOptions": { /* tsconfigの内容 */}, "imports": { // import-mapの内容 "lodash": "https://esm.sh/lodash", "fs": "https://deno.land/std/node/fs.ts" }, "permissions": { // 権限フラグの設定 "allow-all": true, "allow-env": true, "allow-hrtime": false, "allow-read": [ ".", "/tmp" ], "allow-write": ".", "allow-net": "deno.land,nest.land" }, "tasks": { // タスクランナー "run": "./mod.ts", "build": "--allow-read --allow-write ./build.ts", "lint": "src/*.ts", "test": { "args": "--unstable", "permissions": { /*権限フラグの設定*/ }, } } } また、deno.jsonはコマンドの--congigフラグで指定する必要がありますが、対象ディレクトリから自動で読み取るようにすることも検討されています。 毎回コマンドで権限を設定するのは面倒なので、早く導入されて欲しい所です。タスクランナーはpackage.jsonで設定するnpmスクリプトに近いですね。 関連:#3179、#12763、#12764、#12800、#11907 dnt dntはdeno向けモジュールをNode.js向けに変換するツールです。 さきほど紹介したNode.js互換モードは、Node.js向けに書いたコードをDenoで使うためのものでした。dntはその逆で、Deno向けに書いたコードをNode.jsで使うための物です。 現在は、Denoの組み込み関数をNode.jsでpolyfillする作業中のようです。 deno.landからブラウザ向けのモジュール配信 ブラウザから直接deno.land/stdやdeno.land/xのモジュールをimportできるようにするという提案が出ています。 現在でもJavaScriptで書かれたモジュールはブラウザからimport可能ですが、TypeScriptもJavaScriptに変換された上で配信されるようになるため、標準ライブラリなどのtsファイルもブラウザにimportできるようになります。 なおJSに変換されるのはブラウザからアクセスされた時だけで、Deno上ではこれまで通りTypeScriptを使うことができます。 関連:dotland#1902 signal系APIの変更・安定 Deno.Signalをenumから文字列のUnion Typeに変更 これまでDeno.SignalはTypeScriptのEnumによって実装されていました。OSごとに複数のemumを管理するのは冗長だということで、単純な文字列のUnion Typeに変更されました。 v1.14.0で導入されました。 関連:#11900 Deno.addSignalListenerの追加 Deno.addSignalListenerは、Signalが発生した時に実行する関数を設定する機能です。これまではDeno.Signalをfor-await-ofで待ち受けるというAPIでしたが、これがイベントベースの形式に変更されました。合わせて標準ライブラリのsignals/onSignalも非推奨化・削除されます。 v1.16.0で導入されました。 v1.15.3以前 for await (const _ of Deno.signal(Deno.Signal.SIGINT)) { console.log("SIGINT"); } v1.16.0以降 Deno.addSignalListener("SIGINT", ()=>console.log("SIGINT")); 関連:#11158、deno_std#1644 --no-check=remoteフラグの導入 これまでTypeScriptの型チェックは、全てのファイルをチェックするか全くチェックしないかの2択でした。このフラグが導入されると、「外部の依存関係のコードは型チェックしない」という事が可能になります。 関連:#11970、#12766 Deno2.0で導入予定の新機能 11月に予定されていたDeno2.0ですが、Node.js互換モードの完成まで延期されました。 ここでは、元々11月に予定されていた2.0リリースで入る予定だった機能を解説します。 2.0はメジャーリリースのため、破壊的変更が入ります。 参考:2.0のダッシュボード、2.0リリースプラン 新機能 新しいサブプロセスAPI 現在のDeno.runに代わる新しいサブプロセスAPIとして、Deno.Commandが導入されます。 型定義を見ると、以下のような使用方になると思われます。 使用方(推測) const res = new Deno.Command("cat", { args: ["./foo.txt"] }).outut(); console.log(res) // catコマンドの出力 これは後方互換性が無い変更ではないなので、2.0より前のリリースで入るかもしれません。 関連:#11016、#5501、#11618 デフォルトでロックファイルを使用する deno runコマンドの--lockフラグを使うと、依存モジュールのチェックサムを検証することができます。この動作がデフォルトになります(--lockフラグが無くてもロックファイルを使用する)。 関連:#11971 動的import/Workerの権限をチェックする--allow-import=<allow_list>フラグ 現在、動的importやWorkerの作成には--allow-readフラグや--allow-netフラグが必要です。これらのフラグはallow-read=./foo/,./bar/等の構文で許可を与える範囲を制限することができますが、importするファイル全てを指定する必要があるため、フラグが長くなってしまうという欠点があります。--allow-importフラグを導入することで、エントリポイントに対してimportが許可されているディレクトリを指定することができるようになります。 関連:#8266 NotCapableエラー ファイルの読み書き時にPermissionDeniedエラーが発生することがありますが、これの原因は Deno自体のサンドボックス機構によって発生したもの(--allowフラグの付け忘れ) OS側の権限不足によって発生したもの(chmodする必要がある) の2通りあり得ます。どちらによってエラーが発生したのかを区別するため、新たにNotCapableエラーを導入することが検討されています。 関連:#7394 TypeScript関連 実行時の型チェックをオプションにする 現在は、実行時には毎回型チェックが走っています(厳密にいうと毎回チェックされているわけではなく、結果はキャッシュされています)。実行時の型チェックを無効にするには--no-checkフラグを付ける必要があります。 Deno2.0では、フラグ無しの時は従来の--no-checkフラグ付きと同じ動作になり、型チェックを行いたい時は--checkフラグを付けなければいけないようになります。 また、合わせて型チェックのみを行うdeno checkコマンドも導入されます。 デフォルトでは型チェックを行わなくなることに対して、賛成派の意見として以下のようなものを見かけました。(discord等で見かけただけのやつもあります) 型チェックが遅い 初めて使う人にとってはTypeScriptのエラーが分かりにくい IDEを使っていれば、型チェックで出るエラーはエディタ上に表示される 今後のWeb標準との互換のため (Next.jsなど)ESbuild・swcを使用する他のツールは型チェックをしないのが主流になってきている 「今後のWeb標準との互換のため」というのは、今後JavaScriptの仕様にTypeScript構文(またはそれに準ずるもの)が導入されることを見越してのようです。JSの仕様にTS構文が入った場合、ランタイムがコードを実行する時には型チェックを行わないだろうという見方が大きく、そういった今後の仕様に合わせるという意味で型チェックをしないという事です。 一方、反対意見も出ています。 型チェックはキャッシュされるため、遅さを感じるのは初回実行時だけ TSの型エラーが不要な時はJSを使えばいい 全員がIDEを使っているわけではない このように反対意見が出ているものの、一応この変更を入れる方向で動いているようです。 合わせてdeno test --no-runコマンドも削除されます。このコマンドは型チェックだけを行うコマンドでしたが、--no-checkがデフォルトになると何も実行しないコマンドになってしまうので削除されます。 CI等への影響を考慮して2.0での導入が予定されています。 関連:#8549、#11340、#11810、#11786、#11915 デフォルトのtsconfigのみ使用可能にする tsconfig.jsonのcompilerOptionはコマンドの--configフラグで指定できます。しかし、複数のライブラリがそれぞれ異なるtsconfigを使用している場合はどうでしょうか。ライブラリのユーザーが指定できるのは1つのtsconfigだけなので、異なるtsconfigを持つライブラリを同時に使用できません。 このように、人々が各々のtsconfigを使って開発するとモジュール間に分断が生まれるため、デフォルトのtsconfig以外を使用不可にしようという提案が行われています。 ただし、 デフォルトのtsconfigには何を指定すべきか 将来的にデフォルトのtsconfigが変わった場合、移行のために変更前のtsconfigを指定できないと困るのではないか といった点を検討中なため、まだ導入が確定しているわけではなさそうです。 特に、依存関係の奥深くにtsconfig由来のエラーが出ている場合に対処のしようが無いので、困ってしまいます。この問題に対処するため、次項のような提案も出ています。 関連:#7732、#12111 外部コードのTypeScript診断を無視する 外部の依存関係の中からTSエラーが出ている場合、これをユーザーが修正するのは困難です。特に、Deno本体でデフォルトのtsconfigを更新するとライブラリからエラーが出てしまい、更新ができないという問題が実際に発生しています(useUnknownInCatchVariablesの時など)。 こうした状況に対処するため、外部の依存関係から発生したTSエラーを無視するようにするという提案が出ています。 Deno1.17で--no-check=remoteフラグが導入され、2.0でこのフラグを指定した状態がデフォルトになります。 関連:#11970、#12766 JSXファクトリ関数をReact.createElementからhに変更 JSXをトランスパイルする時に、どの関数にトランスパイルするかを表すのがJSXファクトリ関数です。現在のデフォルトはReact.createElementですが、そもそもDenoではデフォルトがReactである必要はあまりないため、これをhに変更します。 既にdeno deployはデフォルトがhになっており、これと挙動を合わせる形となります。 関連:#11186 非推奨 or 不要な機能の削除 Deno.customInspectの削除 Deno.customInspectは、Symbol.for("Deno.customInspect")が導入される前に使われていたプロパティで、現在は非推奨になっています。2.0でこれを削除します。 関連:#10929 evalコマンドの--tsフラグを削除する 既に非推奨になっているevalコマンドの--tsフラグが削除されます。削除後は--ext=tsフラグを使用する必要があります。 関連:#12198 JSで実装されているio関数をDeno本体から標準ライブラリに移動する Deno本体にある関数には、JSのみで実装されているものがあります。Denoの内部で実装するのはOSのシステムコールが必要なものに絞り、rustの呼び出しが不要なものは標準ライブラリから提供することで、ブラウザ互換性が向上します。 既に実装の移動は完了しており、非推奨扱いでDeno本体に残っている関数や型定義が2.0で削除されます。 関連:#9795 ridを使用するDenoメソッドを削除する Deno.openで開いたファイルハンドラからreadする方法は、直接.read()メソッドを呼ぶ方法と、Deno.read(rid)を使う方法の2種類あります。 const file = await Deno.open(new URL("./test.json", import.meta.url)); const buf = new Uint8Array(1); file.read(buf); // パターン1 Deno.read(file.rid, buf); // パターン2 ridを直接操作する方法はあまり使われておらず、またバグの原因にもなるため、削除されます。 Deno.read以外に、Deno.write、Deno.fsyncSync、Deno.fsync、Deno.fdatasyncSync、Data.fdatasync、Deno.flock、Deno.flockSync、Deno.funlock、Deno.funlockSyncも同様に削除されます。 関連:#12107 デフォルト値の変更 Worker内でデフォルトでDeno APIを有効にする 現在はデフォルトではWorker内でDeno APIを使うことはできません。使うためには、Workerの作成時に{deno: true}を指定します。 new Worker("./foo.js", { deno: true, // これを指定するとWorker内でDeno APIを使うことができる }); 2.0ではこれがデフォルトで有効になり、無効化するためには{deno: false}を指定するようになります。 関連:#8174 ProcessStatus.signalの引数をnumberからstringに変更 Deno.signal型がenumからstringのUnion型に変更されたのに合わせて、ProcessStatus.signalの引数がnumberからstringに変更されます。 ProcessStatusはDeno.run()で生成したサブプロセスのステータスを表す型で、既にstableな(=マイナーリリースで破壊的変更が無い)APIなので、2.0で変更されます。 関連:#11912 deno runコマンドで拡張子が無いファイルを実行する場合、TypeScriptとして扱う 現在は拡張子が無いファイルはJavaScriptとして扱われています。これをTypeScriptとして扱うように変更します。 関連:#12220 まとめ 上で紹介した以外にも新機能やバグ修正が盛んに行われています。特に第4四半期正式提供とされているdeno deployは、手軽にサーバーを建てる手段として使っていきたいです。 ※内容に間違いがある場合はコメントで指摘してもらえると嬉しいです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SVGのパスについて詳しく調べてみる(SVG.js)

SVGのパス関係の知識が必要になってきたので仕様を確認していきます。本記事では直接HTMLなどでは書かずにSVG.jsを使っていきます(ただしパスの仕様自体はHTMLでやってもSVG.jsを使っても変わりません)。 以下のMDNやsvg.jsのドキュメントを見ていきます。 使うもの SVG.js v3.1.1 JSFiddle (例 : https://jsfiddle.net/yar6x4hk/202/ ) パスの描画の基本 表示の確認のためにまずはパスの確認用の描画のインスタンスの生成処理について触れていきます。パスを描画するためにはpathメソッドを使います。引数に各パス設定の文字列を指定します。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 100 Q 100 20 150 100 T 250 100'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); パスの位置を移動させるM パスの位置を移動させるにはM <X座標> <Y座標>といったように指定します。例えばX=50, Y=100の位置に移動させたければM 50 100といったように書きます。Mはmove toのMのようです。 パスの位置が変更になるだけでこの記述だけでは表示上には影響しません(これだけだと何も表示されません)。 直線を描画するL 指定位置に向かって直線を描画したい場合にはL <X座標> <Y座標>といったように指定します。例えばX=50, y=50の位置からX=150, Y=50の位置に直線を描画したい場合にはM 50 50 L 100 50といったように書きます。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 50 L 150 50'); path.attr({stroke: '#333', 'stroke-width': 5, fill: '#fff'}); パスの指定はどんどん繋げていくことができる パスの指定はどんどん繋げていくことができます。例えば以下のように2つ目のLを指定すれば折れ線となります。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 50 L 150 50 L 150 150'); path.attr({stroke: '#333', 'stroke-width': 5, fill: '#fff'}); Mを複数入れて複数の線を描画する・・・といったこともできます。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 50 L 150 50 M 50 150 L 150 150'); path.attr({stroke: '#333', 'stroke-width': 5, fill: '#fff'}); 水平方向に対する直線を描画するH H <X座標>とすることで水平方向に対する直線を描画することができます。Lと似たような感じとなりますがY座標の指定が要らなくなるため水平方向の直線を描きたい場合にはこちらの方がシンプルです。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('m 50 50 H 150'); path.attr({stroke: '#333', 'stroke-width': 5, fill: '#fff'}); 垂直方向に対する直線を描画するV V <Y座標>とすると垂直方向に対する直線を描画することができます。Hと対になる設定となります。こちらも水平方向の座標を変えない場合にはLよりも記述がシンプルになります。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('m 50 50 V 150'); path.attr({stroke: '#333', 'stroke-width': 5, fill: '#fff'}); 終点と始点を繋げるZ パスの最後にZと終点と始点のパスを繋げることができます。Lなどで始点の座標を指定するのと同じ挙動になりますがこちらの方がシンプルですし始点の座標を変えた際などにも楽です。 以下の例ではX=150, Y=150の位置からZの記述によってX=50, Y=50の始点に線が繋がれています。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('m 50 50 H 150 V 150 Z'); path.attr({stroke: '#333', 'stroke-width': 5, fill: '#fff'}); パスの塗りを透明にする設定 デフォルトだとパスの内部は塗り設定がされます(フォトショやイラレなどでお馴染みな感じの挙動になります)。以下のようにfill設定をしていないと黒く塗られます。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('m 50 50 H 150 V 150 Z'); path.attr({stroke: '#333', 'stroke-width': 5}); fillにnullや空文字などを指定しても塗りが消えず、透明度設定をすると線も消える・・・感じだったためここまでのコードサンプルでは線のみが見えやすくなるように背景色と同じ白色を塗りに設定していましたが、MDNの資料を読んでいたらどうやらtransparentとfillに設定することで塗りだけ透明にして線のみを表示することができるようです。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('m 50 50 H 150 V 150 Z'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); 小文字による想定値指定 LやH、Vなどの記号は小文字にすると座標の指定が相対値による指定となります(前節までで触れてきた大文字による指定は絶対値による座標の指定です)。 例えばh 50とすれば今の座標から50加えたX座標に線を引く形となり、h -50といったように負の座標を指定すれば今の座標から50左側に移動したX座標の位置に線を引く形となります。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 50 h 50 v 50 h -50'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); 3次ベジェ曲線の指定 フォトショやイラレなどのAdobeソフト、もしくは3Dなどのソフトを使われている方にはお馴染みのベジェ曲線について触れていきます。制御点の指定を2つ必要とする3次ベジェ曲線と1つのみ必要とする2次ベジェ曲線の2つがありますが、まずは3次ベジェ曲線について触れていきます。 記法としてはC <1つ目の制御点のX> <1つ目の制御点のY> <2つ目の制御点のX> <2つ目の制御点のY> <曲線の末端のX> <曲線の末端のY>といった具合にXとY座標がそれぞれ3つずつ必要になります。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 100 C 50 50 100 50 100 100'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); 分かりやすいように各座標に円を追加してみます。先頭のXとYの指定(1つ目の制御点)がシアン、真ん中のXとYの指定(2つ目の制御点)がマゼンタ、3つ目のXとYの指定(曲線の末端)を緑に設定しています。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 100 C 50 50 100 50 100 100'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); var circle1 = draw.circle(10); circle1.x(50 - 5); circle1.y(50 - 5); circle1.fill('#0af'); var circle2 = draw.circle(10); circle2.x(100 - 5); circle2.y(50 - 5); circle2.fill('#f0a'); var circle3 = draw.circle(10); circle3.x(100 - 5); circle3.y(100 - 5); circle3.fill('#0fa'); 他と同様に小文字のcを使うことで相対座標で指定することができます。注意点として基準点は全て始点となります。2つ目の制御点は曲線の末端を基準にしたりはしないようです。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 100 c 0 -50 50 -50 50 0'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); 3次ベジェ曲線の曲線を滑らかに繋ぐS 滑らかに曲線を繋ぎたい場合はSを使います。この場合1つ目の制御座標は前の曲線のものの対向(反転させた位置)のものが使われるため指定が不要になります(対向の座標の制御点が使われるためスムーズな曲線を表現できます)。つまり制御点のXとYの指定が1つのみとなります(イラレのペンツールなどでもベジェ曲線で片方を伸ばしたら対向の制御点も同じ感じで伸びたりしますがそれに近い感じの挙動になります)。S <制御点X> <制御点Y> <曲線の末端のX> <曲線の末端のY>といった形で指定します。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 100 C 50 50 100 50 100 100 S 150 150 150 100'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); 以下のコードではSによる制御点の指定箇所をシアン、曲線の末端の座標の指定箇所をマゼンタの円で表示しています。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 100 C 50 50 100 50 100 100 S 150 150 150 100'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); var circle1 = draw.circle(10); circle1.x(150 - 5); circle1.y(150 - 5); circle1.fill('#0af'); var circle2 = draw.circle(10); circle2.x(150 - 5); circle2.y(100 - 5); circle2.fill('#f0a'); 他と同様に小文字のsを使うことで始点の座標からの相対座標で指定していくことも可能です。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 100 C 50 50 100 50 100 100 s 50 50 50 0'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); 2次ベジェ曲線の指定 2次ベジェ曲線では制御点は1つのみ使います。細かい制御が効きづらくなる一方で記述がシンプルになるため、2次ベジェ曲線で事足りる場合などに便利です。 記法としてはQ <制御点のX> <制御点のY> <曲線の末端のX> <曲線の末端のY>といったように指定します。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 100 Q 100 20 150 100'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); 以下の記述では設定している制御点をシアン、曲線の末端の座標をマゼンタの円で表示しています。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 100 Q 100 20 150 100'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); var circle1 = draw.circle(10); circle1.x(100 - 5); circle1.y(20 - 5); circle1.fill('#0af'); var circle2 = draw.circle(10); circle2.x(150 - 5); circle2.y(100 - 5); circle2.fill('#f0a'); 他と同様にqの小文字で始点からの相対値で座標を指定することができます。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 100 q 50 -80 100 0'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); 2次ベジェ曲線の曲線を滑らかに繋ぐT 3次ベジェ曲線と同様に2次ベジェ曲線でも曲線を滑らかに繋ぐためのTの指定が存在します。こちらは制御点の指定は無くなります(直前の制御点の対向の位置が使われる形になります)。T <曲線の末端のX> <曲線の末端のY>といったように書きます。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 100 Q 100 20 150 100 T 250 100'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); 他と同様にtの小文字で始点からの相対値で末端の座標を指定することができます。 var draw = SVG().addTo('body').size(600, 600); var path = draw.path('M 50 100 Q 100 20 150 100 t 100 0'); path.attr({stroke: '#333', 'stroke-width': 5, fill: 'transparent'}); 曲線に円弧を使うAもあるものの・・・ 他にも円弧を使う形のAの指定もあります。が、軽く触って見た感じ結構設定が直観的とは言い難く個人的に使う機会が少なそう・・・という所感を受けたため今回は触れずに終わります。将来必要になってきたらまた深堀りしようと思います。 参考文献・参考サイトまとめ
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

文系卒の新人が伝えたいエンジニアへの道 社内新人研修編

はじめに ここでは僕が新人研修で学んだことを伝えたいと思います。研修期間は3ヶ月です。会社としては上流工程から下流工程までの案件を引き受けている SIer 企業です。その企業がどのような新人研修をしたかというのを参考にしていただけたらなと思います。 新人研修新人研修で行ったことは以下の通りです。 基本的な知識のインプット(SQL, Java, Git, etc..) 社内サービス改善 社内サービス作成 そしてここでは3つ目の社内サービスの作成について話していきたいと思います。 サービス概要 サービスの内容 社内向け書籍購入ウェブアプリケーション 使用用途 社員が読んだ書籍のレビューをし書籍の情報共有をしあう 使用した言語 JavaScript フロントエンド:React バックエンド:Node.js インフラ環境 AWS この開発は新人8人(フロントエンド:4人、バックエンド:4人)で行いました。僕はバックエンド側の担当していたためバックエンド側の話をしたいと思います。またバックエンドの中でもAPI実装チームとインフラ構築チームの2人ずつに分かれて開発を進めていきました。 インフラ環境 ここではこのサービスのインフラ環境の説明をしていきます。MicrosoftやGoogleもクラウドサービスを提供していますが今回はAWSのクラウドコンピューティングシステムを利用してインフラ環境を構築しました。 環境としてはこんな感じです。 流れとしては、クライアントからリクエストを送信し、そのリクエストを Route 53 が受信します。その受け取った情報を Amazon CloudFront に流し Nginx へとリクエストを送ります。その受け取った情報をもとに戻り値を作成しクライアントに適切な情報を返します。 それでは今回使用したツールの紹介をしていきます。 Route 53 Route 53 はAWSの一つです。特徴としては以下があります。 SLA 100% ドメイン登録 低価格 • SLA SLA は Service Level Agreement の略です。サービスレベル合意書やサービス品質保証などと日本語では訳されます。サービス提供者と利用者の間で結ばれるサービスレベル(定義、範囲、内容など)に関する水準を細かく規定しておき、これを破った場合のペナルティについての契約書です。主に通信サービスやクラウドサービス、連絡サーバーで直っでよく用いられます。 • ドメイン登録 Route 53 では新しくドメイン名を登録することができます。また他のレジスト等で登録したドメインをRoute 53 上に移管することもできます。しかし、一度登録したドメイン名は変更できません。 • 低価格 Route 53 の場合使用した分だけ支払う仕組みなので使う側としては安心できるサービスとなっています。 そして Route 53 では負荷が高くなれば自動的にサーバの台数を増やしたりサーバを強化する機能が備わっています。このような性能の良さが Route 53 には備わっています。 Amazon CloudFront Amazon CloudFront はCDN(Contents Delivery Network)の一つで、高い安全性とデベロッパーの利便性を備えています。 CloudFront を導入しているサービスとして以下の事例があります。 Amazon Prime Video Hulu この用に多量のアクセスやデータのリクエストが来たとして対処できるような機能が備わっています。CloudFront の場合、使用した量だけ支払う料金システムになっています。また50GBのデータ送信、200万件のHTTPSリクエストなら1年間無料となっているのでAWS初心者の方でも始めやすいかなと思います。 VPC Virtual Private Cloud の略でAWSアカウント内に構築できる仮想ネットワークです。図にようにVPC内でEC2などのAWSのサービスを配置することができます。またVPCは複数のVPC間の接続も可能です。ネットワーク環境の構築の際、ハードウェア、回線、データセンターなど用意すべきものが多いためコストと時間がかかります。しかし、AWSでVPCをネット環境として準備すると数分でネットワークを構築することでができます。 EC2 AWSを利用する際によく使われるのが EC2 です。EC2は「Amazon Elastic Compute Cloud」の略でクラウド環境において様々な役割を担ってくれます。EC2を利用することで得られるメリットをいくつか挙げてみました。 使用した分だけ課金 インフラ環境構築時間の短縮 冗長化の負荷分散 • 使用した分だけ課金 EC2は従量課金になっているため、使用した分だけの請求が行われます。また3つの料金形態が存在するためそれぞれのサービスの目的によって料金のお得度が変わるため使用する際は料金形態のチェックも必要になるでしょう。 • インフラ環境構築時間の短縮 インフラ環境の構築においてハードウェア設定が必要な物理サーバーなどを使用する場合、設定完了まで数日かかることもありますが、EC2は数分あれば立ち上げが完了します。この圧倒的スピードで環境作成ができるEC2はプロジェクトにメリットを与えるでしょう。 • 冗長化の負荷分散 仮想サーバの複製などが容易にできるため複数の台数を用意することで安定したサーバの運用が可能です。そのためシステムのトラブルで、万が一サーバがダウンしたとしても他のサーバでサービスを運用することが可能です。 Nginx NginxはWebサーバの一つで、Apacheと比べて高速で大量処理が得意といったメリットがあります。静的コンテンツ処理には適しているためBookclubではNginxを採用しました。また設定も簡単にできるため管理者側としては使いやすいサービスになっています。しかし、大量の動的コンテンツの処理には向いないため、動画を扱ったWebサイトなどの運営には適さないでしょう。また初心者に対しての情報が少ないというデメリットもあります。 2021年6月時点でのWebサーバソフトウェアのシェア(出典:W3Techs.com)ではApacheを抜きNginxが1位となっています。 PM2 PM2はNode.jsをアプリケーションごとに本番環境で起動するためのツールです。またログ管理やモニタリング(CPUやメモリ)が可能です。Node.jsアプリケーションのプロセスの状態を常に監視しており、プロセスを自動で再起動させる機能を備えています。PM2は3つのプロダクトがあり、今回のBookclubではPM2 Runtimeを使用しています。 ↑PM2 Runtimeはチェックが必要 Node.js Node.jsはJavaScriptをサーバサイドでも動くようにしてくれるツールです。詳しくいうと、ブラウザ上で動作するJavaScriptをOS上でも動くようにしたのがNode.jsです。しかし、Node.jsはDjangoやLaravelなどのWebフレームワークではなくあくまでもJavaScriptの実行環境です。 Node.jsの特徴は「軽量」であるということです。例えば、リアルタイムで複数の人が使用する場合でもスムーズに動作してくれるという魅力があります。 開発 開発ではAPI作成からテストまでを行いました。順序としては、API仕様書を作成し、それに沿ったコードを実装をしていきました。そしてその実装が正しいか、またサーバの強度は十分に足りているかというテストをしました。 開発の中で僕が印象に残ったものをピックアップし紹介していきます。 Swagger Advanced REST client / Postman Jmeter Swagger 開発で一番最初に躓いた場面がこのSwaggerでした。Swagger とは REST API を構築するためのオープンソースのフレームワークのことです。APIも知らなかった僕はこれがどう開発でいかされるのか全く想像がつきませんでした。書き方が全然わからない中で講師の方に紹介していただいたのがSwagger Editorでした。ここではすでに Swagger のコードが書かれているため、これを参考にサービスの API を作っていきました。 Advanced REST client / Postman ローカル環境で開発をしている際にHTTPのリクエスト送信やレスポンス確認をするために使用したのが Advanced REST client と Postman です。curlをたたいて実行はできますが Advanced REST client これは Google の拡張機能で色んな処理をブラウザ上で実行することができるため便利です。また頻繁に使うリクエストの保存、履歴参照の機能も備わっています。 Postman これは有名な Web API のテストクライアントのひつとです。様々なテストのシナリオを実行することができます。また、認証、テスト、ドキュメント作成、バージョン管理などいろんな種類の要素を統合してテスト開発ができるため、ログイン、非ログインのユーザの実装も簡単にできる便利なツールです。API設計・開発する際は是非使ってみて下さい。 Jmeter Jmeter の説明をしていく前にテそもそもストではどういったことを行なっていったのかの説明から始めます。 テスト 開発で欠かせないのがテストです。テストはもちろんしたことがなかったので、何をどのようにしたらいいか、またどのようなエビデンスを取らなければいけないのかすらわかっていませんでした。 ここで僕たちが行ったテストで必要であった要素を紹介します。 全ての想定される実装の洗い出し 想定された戻り値を返しているか サーバの負荷強度 全ての想定される実装の洗い出し これに関しては自分たちが書いたコードの中で実装されているAPIの洗い出しをしました。 しかし、今思うとディシジョンテーブルを使用するべきだったなと思います。ディシジョンテーブルを使用することでテストの抜け漏れを防ぐことができます。また、テスト直前にディシジョンテーブルを作成するのではなく開発前、設計の段階でディシジョンテーブルを作成する方がよりベターです。 想定された戻り値を返しているか この想定された戻り値に関しては先ほど紹介した Swagger を参照し、どのような戻り値を返さなければいけないのかの確認が必要です。このAPI開発ではAPI仕様書をもとに開発が進められているため、フロント側もバックエンド側も開発を進めてAPI仕様書を見て実装していかなければいけません。ここで使用するツールは Advanced REST client や Postman などももちろん使えますが、この後に紹介する Jmeter を使うことも可能です。 サーバの負荷強度 このサーバの負荷強度でとても役に立ったのが Jmeter です。この Jmeter は良いところは自動的にいくつもの実装を行なってくれる、いわゆる自動化です。この自動化テストを行うことでサーバの強度を図ることができます。 例えば1分間の間にn回サーバにアクセスが来た場合(サイトを開いた、投稿した、投稿を削除した、etc...)の実行結果を出すことができます。この数が多い方がサーバの強度が高いことを意味します。しかし、ここで重要なのがCDNを含まないようにすることです。僕たちは最初いくらnの回数を上げても全てのリクエストが正常に返ってくるため、サーバの強度高いなと勘違いしていました。しかしこれは間違いで僕たちが測っていた強度はサーバではなく CloudFront の強度を測っていたのです。そのため、サーバの負荷テストを行うときはCDNを外すという作業を忘れないようにしなければなりません。 最後に 今回は新人研修で作ったサービスについて書いてみました。いかがでしたでしょうか? インフラ周りなどの担当していない部分についてはまだまだ勉強不足な面がありもっともっと知識をつけなければいけないなとこの投稿を書きながら思いました。 この研修での1番の収穫は「知らないことばかりだな」と知らないことを知ることができました。この先も勉強を続けて知らない部分知り、いろんなものを吸収していこうと思います。 最後まで読んでいただきありがとうございました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LWC 共通モーダル画面を作成

1.目的 LWCでの共通モーダル画面を作成する方法を共通します 2.ソース modal modal.css .slds-modal__content.slds-p-around_medium{ text-align: center !important; } modal.html <template> <!--Use template if:true to display/hide popup based on isModalOpen value--> <template if:true={_isModalOpen}> <!-- Modal/Popup Box LWC starts here --> <section role="dialog" tabindex="-1" aria-labelledby="modal-heading-01" aria-modal="true" class="slds-modal slds-fade-in-open"> <div class="slds-modal__container"> <!-- Modal/Popup Box LWC header here --> <header class="slds-modal__header"> <button class="slds-button slds-button_icon slds-modal__close slds-button_icon-inverse" title="Close" onclick={closeModal}> <lightning-icon icon-name="utility:close" alternative-text="close" variant="inverse" size="small"></lightning-icon> <span class="slds-assistive-text">Close</span> </button> <h2 class="slds-text-heading_medium slds-hyphenate">{title}</h2> </header> <!-- Modal/Popup Box LWC body starts here --> <div class="slds-modal__content slds-p-around_medium"> <lightning-formatted-rich-text value={content}></lightning-formatted-rich-text> </div> <!-- Modal/Popup Box LWC footer starts here --> <footer class="slds-modal__footer"> <button class="slds-button slds-button_neutral" onclick={closeModal}>いいえ</button> <button class="slds-button slds-button_brand" onclick={confirmHandle}>はい</button> </footer> </div> </section> <div class="slds-backdrop slds-backdrop_open"></div> </template> </template> modal.js import { LightningElement, track, api } from 'lwc'; export default class Modal extends LightningElement { @api name; //表示フラグ @track _isModalOpen; //タイトル @track _title; //コンテンツ @track _content; @api openModal() { this._isModalOpen = true; } /** * クローズ */ closeModal(e) { e.preventDefault(); this._isModalOpen = false; let changenEvent = new CustomEvent("confirm", { detail: false, composed: true, bubbles: true, cancelable: true, }); this.dispatchEvent(changenEvent); } /** * 「はい」ボタン押下 */ confirmHandle(e) { e.preventDefault(); this._isModalOpen = false; let changenEvent = new CustomEvent("confirm", { detail: true, composed: true, bubbles: true, cancelable: true, }); this.dispatchEvent(changenEvent); } @api get title() { return this._title; } set title(val) { this._title = val; } @api get content() { return this._content; } set content(val) { this._content = val; } } modal.js-meta.xml <?xml version="1.0" encoding="UTF-8"?> <LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata"> <apiVersion>52</apiVersion> <isExposed>false</isExposed> </LightningComponentBundle> 3.おわり
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【javascript】fetch

fetch サーバー上からデータを取得することができる。 case 取得するデータ形式 json オブジェクトのプロパティは""で囲む 要素の最後にカンマをつけない。 [ { "name": "Bob", "age": 23 }, { "name": "Tim", "age": 30 }, { "name": "Sun", "age": 25 } ] fetch('users.json') //取得先のURLセット console.log(fetch('users.json')) Promise(すなわちthenが使用できる)とResponseが返却されているのがわかる。 responseを覗いてみる。 prototypeにjsonがある。 jsonファイルにアクセスする。 thenで階層を深く潜り、jsonファイルにアクセスできた。 fetch('users.json').then(function(response){ console.log(response) return response.json(); }).then(function(json){ console.log(json) }); jsonファイルを加工する。 fetch('users.json').then(function(response){ console.log(response) return response.json(); }).then(function(json){ console.log(json) for(const user of json){ console.log(`私は${user.name}です。年齢は${user.age}になりました。`) } }); // 私はBobです。年齢は23になりました。 // 私はTimです。年齢は30になりました。 // 私はSunです。年齢は25になりました。 await asyncで書いてみる async function fetchTest(){ const response = await fetch('users.json'); //awaitでpromiseを受け取る。 const json = await response.json(); for(const user of json){ console.log(`私は${user.name}です。年齢は${user.age}になりました。`); } } fetchTest(); // 私はBobです。年齢は23になりました。 // 私はTimです。年齢は30になりました。 // 私はSunです。年齢は25になりました。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【javascript】Async, Await

Async, Await Promiseをより直感的に使用する目的で作成された ES8以上 Async Promiseを返却する関数の宣言を行う。 関数の先頭にAsyncと書くとPromiseを返却することが担保されている。 グローバルコンテキストでは使用できない。関数コンテキストで使用する。 Await Promiseを返却する関数の非同期処理が完了するまで待つ。 case Promiseチェーンもより簡単に書けるようになる。 init()関数でsleep関数を実行する。 asyncは実行する関数が非同期で実行されることを明示している。使用しないとエラーになる。 awaitはresolveで受け取る引数valを受け取ることになる。 すなわちawaitで受け取るのはPromiseのインスタンス 引数valをもつsleep関数でPromiseを実行 setTimeoutで1秒後にresoleve,valをインクリメント function sleep(val) { return new Promise(function(resolve) { setTimeout(function() { console.log(val++); resolve(val); }, 1000); }); } async function init(){ let val = await sleep(0) val = await sleep(val) val = await sleep(val) val = await sleep(val) } init(); >>> 0 >>> 1 >>> 2 >>> 3
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【javascript】async, await

async, await Promiseをより直感的に使用する目的で作成された ES8以上 async Promiseを返却する関数の宣言を行う。 関数の先頭にasyncと書くとPromiseを返却することが担保されている。 グローバルコンテキストでは使用できない。関数コンテキストで使用する。 await Promiseを返却する関数の非同期処理が完了するまで待つ。 case Promiseチェーンもより簡単に書けるようになる。 init()関数でsleep関数を実行する。 asyncは実行する関数が非同期で実行されることを明示している。使用しないとエラーになる。 awaitはresolveで受け取る引数valを受け取ることになる。 すなわちawaitで受け取るのはPromiseのインスタンス 引数valをもつsleep関数でPromiseを実行 setTimeoutで1秒後にresoleve,valをインクリメント function sleep(val) { return new Promise(function(resolve) { setTimeout(function() { console.log(val++); resolve(val); }, 1000); }); } async function init(){ let val = await sleep(0) val = await sleep(val) val = await sleep(val) val = await sleep(val) } init(); >>> 0 >>> 1 >>> 2 >>> 3
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【javascript】Macrotasks, Microtasks

Macrotasks, Microtasks Macrotasks タスクキューと呼ばれるもの。 setTimeoutなど Microtasks ジョブキューと呼ばれる。タスクキューとは別の非同期処理の待ち行列 Promiseなどの非同期処理 case どの順番でコンソールに表示されるか? setTimeout(function task1() { console.log('task1'); }); new Promise(function promise(resolve) { console.log('promise'); resolve(); }).then(function job1() { console.log('job1'); }); console.log('global end'); 以下の順番で実行される。 グローバルタスク(同期処理) console.log('promise'); console.log('global end'); マイクロタスク(非同期処理) console.log('job1'); マクロタスク(非同期処理) console.log('task1'); すなわち、コールスタックで呼ばれた種類によって登録先を決めている。 イベントループがマイクロタスク(ジョブキュー)なのかマクロタスク(タスクキュー)なのかを振り分けて実行する優先順位を決めている。 実行挙動の違い MicroTasks(ジョブキュー) 登録されているすべてのジョブを実行する。 MacroTasks(タスクキュー) 登録されているタスクを一つづつ実行する。 コールスタック マイクロタスク マクロタスク context job1 task1 job2 task2 マイクロタスクを全て実行 コールスタック マイクロタスク マクロタスク context task1 task2 その後マクロタスクを一つ実行 コールスタック マイクロタスク マクロタスク context task2 マイクロタスクが追加された場合 コールスタック マイクロタスク マクロタスク context job1 task2 マイクロタスクが実行され コールスタック マイクロタスク マクロタスク context task2 * またマクロタスクが一つタスクを実行される。 コールスタック マイクロタスク マクロタスク context case2 マクロタスクからマイクロタスクを読んだ場合はマクロタスクから実行される。 setTimeoutからPromiseをcall new Promise(function promise(resolve) { console.log('promise'); setTimeout(function task1() { console.log('task1'); resolve(); }); }).then(function job1() { console.log('job1'); }) case3 queueMicrotaskを利用するとマイクロタスクに差し込みができる。 new Promise(function promise(resolve) { console.log('promise'); setTimeout(function task1() { console.log('task1'); resolve(); }); }).then(function job1() { console.log('job1'); queueMicrotask(function job4(){ //thenのなかでマイクロタスクを追加した。job2の前にjob4が実行される。 console.log('job4') }) }) .then(function job2() { console.log('job2'); }).then(function job3() { console.log('job3'); }) console.log('global end'); case3 queueMicrotaskを使用するとマイクロタスクに差し込みができる。 new Promise(function promise(resolve) { console.log('promise'); setTimeout(function task1() { console.log('task1'); resolve(); }); }).then(function job1() { console.log('job1'); queueMicrotask(function job4(){ //thenのなかでjob4を差し込んでいる。よってjob2の実行前にjob4が実行される。 console.log('job4') }) }) .then(function job2() { console.log('job2'); }).then(function job3() { console.log('job3'); }) console.log('global end'); タスクの代表例 Macrotasks setTimeout setInterval requestAnimationFrame Microtasks Promise queueMicrotask MutationObserver
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Webの勉強はじめてみた その5 ~JavaScript編 演算子~

今日も1コマ。 論理値について勉強しました。 if文って基礎にしてかなり厄介な気がする。 そういやSelect文ってあるんだっけ。JSはSwitchか。 今日やったこと 1. 比較演算子 2. 論理演算子 気付いたこと 1. 比較演算子 == と === != と !== 曖昧さをとにかく排除するなら===や!==を使うのがいい。 変数の宣言に型の明示を必要としないから、こういうのも気をつけたほうがいいのかも。 変数の初期値にnull VB.Net だと宣言した型によって空文字とか0を入れてた。 どっちがいいんだろう。 2. 論理演算子 否定(NOT): ! 論理和(OR): || 論理積(AND): && 排他的論理和(XOR) 試される国語力。。 ビット演算子と区別するために記号を重ねてるらしい。 以前にphpで使ったことあるけれどビットはややこしかった。 論理値を扱う変数はあたまにisをつける 言語によって違いそうだけど、頭に置いておく。 まとめ 変数名に直接的な英単語が多いのかなという印象。 .NETだと予約されてる単語や名前空間が多かったので、少し違和感。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Webの勉強はじめてみた その5

今日も1コマ。 論理値について勉強しました。 if文って基礎にしてかなり厄介な気がする。 そういやSelect文ってあるんだっけ。JSはSwitchか。 今日やったこと 1. 比較演算子 2. 論理演算子 気付いたこと 1. 比較演算子 == と === != と !== 曖昧さをとにかく排除するなら===や!==を使うのがいい。 変数の宣言に型の明示を必要としないから、こういうのも気をつけたほうがいいのかも。 変数の初期値にnull VB.Net だと宣言した型によって空文字とか0を入れてた。 どっちがいいんだろう。 2. 論理演算子 否定(NOT): ! 論理和(OR): || 論理積(AND): && 排他的論理和(XOR) 試される国語力。。 ビット演算子と区別するために記号を重ねてるらしい。 以前にphpで使ったことあるけれどビットはややこしかった。 論理値を扱う変数はあたまにisをつける 言語によって違いそうだけど、頭に置いておく。 まとめ 変数名に直接的な英単語が多いのかなという印象。 .NETだと予約されてる単語や名前空間が多かったので、少し違和感。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ajaxのソースコード

実務でJavaのシステムで実装したAjaxのソースコードを自分用にメモとしてまとめました。 まずはJavaScriptでイベントを作成し、通信する。 $('#button').click(function() { var req = new XMLHttpRequest(); var url = 'コンテキスト以降のURL'; req.open('GET',url); req.send(); req.onreadystatechange = function() { if (req.readyState === 4 && req.status === 200) { let info = (req.responseText)?JSON.parse(req.responseText):null; if (info) { console.log(info); } } } }); 指定したURLのサーブレットを作ってJSONデータを返す。 // レスポンス用JSON文字列生成 String resData = "{\"mojiretsu1\":\"" + "mojiretsu1" + "\",\"mojiretsu2\":\"" + "mojiretsu2" + "\",\"mojiretsu3\":\"" + "mojiretsu3" + "\"}"; // レスポンス処理 response.setContentType("text/plain"); response.setCharacterEncoding("utf8"); PrintWriter out = response.getWriter(); out.println(resData); 文字列はtry,catch構文でデータベースに接続してデータベースから取ってきたり、サーブレットで生成したりする。 以上です。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[JavaScript]onloadイベントについて

onloadイベントとは HTMLページに含まれるすべてのリソースの読み込みが完了したら発生するイベント。 onloadの書き方 基本的なonloadイベントの書き方は以下となる。 window.onload = funcrion(){ // 処理内容 } 上記のようにwindowを指定すると、HTMLページに含まれるすべてのリソースが読み込まれた後に処理内容で指定された処理が実行される。 また、windowの部分に「img」などのHTML要素を指定することもできる。この場合、指定された要素の読み込みが完了した時点で処理が実行される。 さらに、addEventListenerを使って以下のように書くこともできる。 window.addEventListener('load',function(){ // 処理内容 }) この2つの違いとして、同じ要素に複数のイベントハンドラーを設定することができるかどうかです。 onloadの場合は上書きされるため、最後に設定された処理だけが実行される。一方で、addEventListenerは上書きされないため、設定されたすべての処理が実行される。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Core Web VitalsのフィールドデータをConsoleのみで確認する方法

自分がページを開いたときのCLS, LCP, FID のようなCore Web Vitalsのフィールドデータを確認するためには 公式のChrome拡張機能を使うのが一番ラクですが、諸事情あって拡張機能を利用できない場合はChrome DevToolsのConsoleパネルから以下のスニペットを動かすことでも確認可能です。 BASIC認証がかかった検証用のページでも利用可能です。 import('https://unpkg.com/web-vitals?module') .then((module) => { module.getCLS(console.log); module.getFID(console.log); module.getLCP(console.log); console.log('Please switching tabs and then switching back.'); }); 本スニペットはGoogle公式のCore Web Vitalsのフィールドデータを確認するためのコードをConsole上でスマートに動かせるように動的インポート の形に変更して作成しています。 使い方 Chrome DevToolsのConsoleパネルを開きます。 ページの読み込みが完了するまで待ってConsoleにスニペットを貼り付けてEnterキーを叩きます。 ページ内のボタンやリンクをクリックするとFIDの数値が出力されます。 ブラウザの別のタブを開いてもう一度スニペットを動かしたタブに戻ってくるとLCP, CLSの数値も出力されます。 このような動作をする理由 Note that some of these metrics will not report until the user has interacted with the page, switched tabs, or the page starts to unload. If you don't see the values logged to the console immediately, try reloading the page (with preserve log enabled) or switching tabs and then switching back. Also, in some cases a metric callback may never be called: ・FID is not reported if the user never interacts with the page. ・FCP, FID, and LCP are not reported if the page was loaded in the background. In other cases, a metric callback may be called more than once: ・CLS should be reported any time the page's visibilityState changes to hidden. ・CLS, FCP, FID, and LCP are reported again after a page is restored from the back/forward cache. https://github.com/GoogleChrome/web-vitals#basic-usage 公式のChrome拡張機能と数字を見比べてみると同じデータを確認できていることが分かります。 (四捨五入による処理で僅かに異なる数値となる場合もあります) 出力結果の見方 value: 各指標の出力時点での数値 delta: 同じページビュー中に数値の更新があった場合、前回報告したときのスコアとの差分 実際に検索順位に影響を与えるページエクスペリエンスシグナルが考慮する数字は過去28日間にGoogleに送信された十分な量のフィールドデータの内75パーセントタイルの成績です。 右向きの三角形が付いた行はクリックすることで展開することができます。 出力結果のentriesを展開することで各数値に影響を与えた要素の情報を確認することが可能です。 その他 コードに記述を加えることによりTTFBやFCPの値を確認することも可能です。 import('https://unpkg.com/web-vitals?module') .then((module) => { module.getCLS(console.log); module.getFID(console.log); module.getLCP(console.log); module.getFCP(console.log); module.getTTFB(console.log); console.log('Please switching tabs and then switching back.'); }); CoreWebVitalsのスコアを確認する様々な方法
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WebブラウザでOSのダークモード判定 ~社内で大不評の【誰得?】シリーズ~

パーソンリンク アドベントカレンダー2日目です!? 内容 window.matchMedia('(prefers-color-scheme: dark)').matches これがtrueの場合にはdarkモード。 なにこのシリーズ 社内で不評なたまに呟く「誰の得になるの!?」シリーズです。 さようならー
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Webブラウザの判定 ~社内で大不評の【誰得?】シリーズ~

パーソンリンク アドベントカレンダー9日目です!? 内容 const UA = window.navigator.userAgent.toLowerCase(); if (UA.indexOf('msie') != -1 || UA.indexOf('trident') != -1) { console.log('IE'); } else if (UA.indexOf('edge') != -1) { console.log('Edge'); } else if (UA.indexOf('chrome') != -1) { console.log('Chrome'); } else if (UA.indexOf('safari') != -1) { console.log('Safari'); } else if (UA.indexOf('firefox') != -1) { console.log('Firefox'); } else if (UA.indexOf('opera') != -1) { console.log('Opera'); } else { console.log('None'); } ブラウザによって内容変えたいのであればこれでいけるはず。 なにこのシリーズ 社内で不評なたまに呟く「誰の得になるの!?」シリーズです。 さようならー
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

期間限定でCSSを切り替える ~社内で大不評の【誰得?】シリーズ~

パーソンリンク アドベントカレンダー16日目です!? 内容 <link id="StyleSheetFilePath" rel="stylesheet" href="base.css" /> <script> window.onload = function() { var nowDate = new Date(); var startDate = new Date('2021/12/24 0:00:00'); var endDate = new Date('2021/12/25 23:59:59'); if ( startDate < nowDate && nowDate < endDate ) { var styleSheetFilePathElement = document.getElementById("StyleSheetFilePath"); styleSheetFilePathElement.href = "xmas.css"; } } </script> クリスマス限定でCSSを切り替えたいのであればこれでいけるはず。 (試してないので多分としか言いようがないけど。。。) JavaScriptで日付とかは持たない方がいいけどね。PCの時間変えられたら意味ないので。。。 なにこのシリーズ 社内で不評なたまに呟く「誰の得になるの!?」シリーズです。 さようならー
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Node.jsメモ】require()の使い方

require()とは Node.jsでモジュール化された「便利なJavaScriptファイル」を呼び出すためのもの。 const 変数= require('モジュール名'); サーバーサイドでの開発に優しい こうやってモジュールを呼びだせば自分で難しいアルゴリズムを考えてプログラミングする手間が省けます
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[note] js online editor

*playcode https://playcode.io/178820?tabs=console&script.js&output *jsfiddle https://jsfiddle.net/pek06c9v/ *codesandbox https://codesandbox.io/ *stackblitz https://stackblitz.com/ *jsbin https://jsbin.com/?html,output *ts – playground http://www.typescriptlang.org/play/index.html *p5js editor https://editor.p5js.org/
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【JavaScript】モジュール④ モジュールの特徴

はじめに Udemyの【JS】ガチで学びたい人のためのJavaScriptメカニズムの講座の振り返りです。 前回の記事 目的 モジュールについての理解を深める 本題 1.モジュールの特徴 前提 index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <script> const span = document.createElement('span'); span.textContent = decodeURI(window.location.pathname); document.body.appendChild(span); </script> <h2>編集用ファイル</h2> <a href="../end" style="font-weight: 600; color: red;"> 完成ファイルへ </a> <div> <a href="../../" style="margin-right: 10px;"> セクションへ </a> <a href="../../../"> コースへ </a> </div> <!--スクリプトファイルでmain.jsを読みこむ--> <script src="main.js" defer></script> <!--typeモジュールでmoduleBを読みこむ--> <script type="module" src="moduleB.js"></script> </body> </html> 例1 type = moduleという属性をつけた場合には後に続く読み込みのファイルは非同期になる index.html <body> : <!--中略--> : <!-- h1 タグを生成 --> <h1>モジュールレクチャー</h1> <script src="main.js" defer></script> <script type="module" src="moduleB.js"></script> </body> main.js // documentのquerySelectorというメソッドを使ってh1タグの要素を取得 const h1 = document.querySelector("h1"); // documentというオブジェクトの中にHTMLのタグが格納されている // よってこれらのオブジェクトにアクセスすることで値が取得できる const text = h1.textContent; // モジュールレクチャーと表示される console.log(text); 例2 読み込む順番を入れ替える index.html <body> : <!--中略--> : <!-- textContentが読み込まれなくなる(main.jsが読み込まれたタイミングではまだh1タグが読み込まれていないから) --> <!-- scriptタグが見つかった時点で読み込まれる = 同期的な処理 --> <!-- 非同期にしたい場合にはdeferという属性を付与する --> <script src="main.js" defer ></script> <!-- main.jsが読み込まれモジュールレクチャーと出力される --> <h1>モジュールレクチャー</h1> <script type="module" src="moduleB.js"></script> </body> 例3 type = moduleと書くことでdeferが付与されていることになる index.html <body> : <!--中略--> : <script src="main.js" defer ></script> <!-- h1タグより先に読み込む --> <script type="module" src="moduleB.js"></script> <h1>モジュールレクチャー</h1> </body> moduleB.js // main.jsで書いた処理をmoduleBで書いても同様の出力結果が得られる const h1 = document.querySelector("h1"); const text = h1.textContent; console.log(text); 例4 main.jsは(モジュールでないものは)何回も読み込むとその回数分だけ実行されるが、モジュールは1回のみ読み込まれる main.js // main.jsが読み込まれた時に出力 console.log("main.js") moduleB.js // moduleB.jsが読み込まれた時に出力 console.log("moduleB.js") index.html <body> : <!--中略--> : <!-- コンソールで3度出力される --> <script src="main.js" defer ></script> <script src="main.js" defer ></script> <script src="main.js" defer ></script> <!-- 一度しか出力されない --> <script type="module" src="moduleB.js"></script> <script type="module" src="moduleB.js"></script> <script type="module" src="moduleB.js"></script> </body> importを使用した場合も同様 モジュールは最初の一回のみ 今日はここまで! 参考にさせて頂いた記事 【JS】ガチで学びたい人のためのJavaScriptメカニズム Let'sプログラミング JavaScript入門
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

マリリン・マンソン・ゲーム ~本物の「マリリン・マンソン」を探せ!~

事の顛末 以前,Twitter にてこんなつぶやきを発見しました. 要するに,外国人の日本語学習者に向けて, 「カタカナの『リ』『ソ』『ン』,ちゃんと区別できる?」 「できなかったらもっと練習だぜ!」 「ところで,“Marilyn Manson”ってカタカナでは『マリリン・マンソン』って書くんだぜ!」 というつぶやきです. そこで 0.2kg 君は思いました. 「なるほど,マリリン・マンソンやべぇ」 「この 3 つの読み分け・書き分けは日本語ノンネイティブにはやはり鬼門なのか」 というわけで, 「マリリン・マンソン」を使って「リ」「ソ」「ン」の区別を練習できるゲームを作っちゃおう! という発想から,本記事でご紹介する「マリリン・マンソン・ゲーム」の作成に至りました. これが「マリリン・マンソン・ゲーム」だ! ここでプレイ可能です. ルール 10 秒以内に 25 個の「マリリン・マンソン」とその偽物から,本物の「マリリン・マンソン」を探し当てる. 得点は「(残り時間 [sec])*100-(ミス回数)*10」で計算される. 所感 残り時間で難易度調整ができそうですが,筆者も含めた日本語ネイティブにとっては 10 秒ちょいくらいがクリアできるかできないかのギリギリなんじゃないかと思っています. その後 個人的にノンネイティブの日本語学習者さんの反応が気になったので,知人の外国人留学生 2 人にこのゲームをやっていただきました.その結果, 「選択肢を 2, 3 個読むだけで制限時間終わっちゃった……」 「僕もだよ.制限時間までに 3 つより多くは読めなかったよ.これってスピード勝負のゲームでカタカナの読み分けができてるかのテストじゃない気がする」 という非常に興味深いコメントをいただきました. 「マリリン・マンソン・ゲーム」,どうやら日本語学習にはあまり役に立たないゲームのようです. どっとはらい.
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Salesforce】認定JavaScriptデベロッパー試験対策

はじめに この度JavaScriptデベロッパー試験に合格することが出来たので、情報共有として記事を投稿します。 受験した感想としては、LWCの実装経験と試験に合格できるかどうかは、必ずしもイコールではないな、というものでした。 試験で問われるのはJavaScriptの知識そのもので、LWCの知識は一切問われません。 また、LWCを実装する上では必須とは言えない部分からも出題されるため、LWCの実装経験が豊富だったとしても試験対策は必要だと感じました。 そこで本記事では、LWCを実装する上で見落としがちな、JavaScriptの基本的な仕様について解説したいと思います。 試験範囲で言うと、以下単元に関わる部分のみ解説しています。 網羅的な解説は行なっていないためご了承下さい。 変数、データ型、コレクション オブジェクト、関数、クラス 非同期プログラミング 私の経歴 プログラミング経験:1年半 実務経験:1年(Salesforce開発を担当) LWC実装経験:3機能ぐらい LWC以外に実務でJavaScript開発を行なった経験はありません。 半年前までargumentsも知らなかったレベルです、、 学習した内容 受験を決めてから合格までは約2ヶ月です。 その期間に行なったことを順番に紹介します。 Trailhead:Lightning Web コンポーネントの作成 Trailhead:Study for the Salesforce JavaScript Developer I Exam Udemy:【JS】ガチで学びたい人のためのJavaScriptメカニズム この講座のおかげで合格できたと言っても過言ではありません。 体系的にしっかりJavaScriptを学びたい方にお薦めです。 書籍:JavaScriptモダンプログラミング完全ガイド カバーしている範囲は上記Udemyの動画とほぼ同じです。 私は動画 → 書籍の順番だったので何とか読めましたが、初見だと若干難易度が高い、、? Superbadge:Lightning Web Components Specialist 有志の方々による日本語訳が公開されています。 資格を取得するためには、試験合格とTrailのバッジ獲得が必須条件なので、学習も兼ねて受験前に取り組むことをお勧めします。 解説 前置きが長くなりましたが、いよいよ本題に入ります。 変数、データ型、コレクション var / let / const この辺りは基本中の基本かもしれませんが、現在は非推奨とされているvarを使ったことが無い方向けです。 var:ブロックスコープを形成しない / 巻き上げが行われる let / const:ブロックスコープが形成される / 巻き上げが行われない if(true) { var a = 'a'; let b = 'b'; } console.log(a); // a console.log(b); // ReferenceError console.log(a); // undefined ※巻き上げされた時点では値が未設定 console.log(b); // ReferenceError var a = 'a'; let b = 'b'; 配列操作 ここはLWCの実装でも使用頻度が高い部分だとは思いますが、私はflat()の存在を試験で初めて知った(そして案の定間違えた)ので念の為、、 結合にはスプレッド構文かconcat()を使用 const arry1 = [1, 2, 3]; const arry2 = [4, 5, 6]; const result1 = [...arry1, ...arry2]; const result2 = arry1.concat(arry2); console.log(result1); // [1, 2, 3, 4, 5, 6] console.log(result2); // [1, 2, 3, 4, 5, 6] 連想配列にはflat()を使用、全て展開する場合は引数にInfinityを渡す const arry1 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]; console.log(arry1.flat()); // [1, 2, 3, 4, [5, 6, [7, 8, [9, 10]]]] console.log(arry1.flat(2)); // [1, 2, 3, 4, 5, 6, [7, 8, [9, 10]]] console.log(arry1.flat(Infinity)); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] オブジェクト、関数、クラス オブジェクトのコピー Object.assign({}, obj)で浅いコピー JSON.parse(JSON.stringify(obj))で深いコピー(メソッドの定義があれば消失) const obj1 = { a: 'a', b: 'b', c: { text: 'original' }, d: { text: 'original' }, fn: function() { console.log('hello'); } }; const copy1 = Object.assign({}, obj1); console.log(copy1); // {a: 'a', b: 'b', c: {text: 'original'}, d: {text: 'original'}, fn: ƒ} const copy2 = JSON.parse(JSON.stringify(obj1)); console.log(copy2) // {a: 'a', b: 'b', c: {text: 'original'}, d: {text: 'original'}} // obj1とcopy1は同じオブジェクトを参照している copy1.c.text = 'changed'; console.log(obj1.c.text); // changed copy2.d.text = 'changed'; console.log(obj1.d.text); // original console.log(copy1.c === obj1.c); // true console.log(copy2.c === obj1.c); // false this thisを理解するために大切なポイントは2点です。 アロー関数内ではthisコンテキストが生成されない → そのためthisを参照しようとした場合は外側のスコープを順に辿っていく メソッドではなく関数として呼ばれた場合はthisがwindowオブジェクトを参照する → bind() などを使用しない限りどこで呼んでもthis = window 「アロー関数ではthisコンテキストが生成されない = thisが参照できない」ではないため、アロー関数を使用している1つ上のスコープにthisがあれば参照できます。 逆にオブジェクトから呼ばれるメソッドではなく、関数として呼ばれた場合は基本的にグローバルスコープを参照するため、1つ上の階層にthisが存在してもthis = windowになります。 私は「アロー関数内ではthisの使用不可」と思い込んでいたため、正しくthisが参照できているような例文を見て激しく混乱していました、、 コンテキストやスコープについて理解が進めば、自然にthisの挙動についても理解できるようになると思います。 window.target = 'window'; const target = 'script'; const obj = { target: 'obj', hello1() { console.log(this.target); // obj → 基本的なthisの使用法 const bye = () => { console.log(this.target); // obj → 1つ上のスコープにthisが存在するため'obj'を参照 const traditionalFn = function() { console.log(this.target); // window → 無名関数のため強制的にwindowを参照 } const allowFn = () => { console.log(this.target); // obj → 2つ上のスコープにthisが存在するため'obj'を参照 } traditionalFn(); allowFn(); } bye(); }, hello2: () => { console.log(this.target); // window → アロー関数のためthisが生成されずwindowを参照 const bye = () => { console.log(this.target); // window → 1つ上のスコープにもthisが存在しないためwindowを参照 } bye(); }, } obj.hello1(); obj.hello2(); const copyHello1 = obj.hello1; copyHello1(); // 出力は全てwindow copyHello1.call(obj); // 出力は全てobj.hello1()と同様 → copyHello1()のthisを強制的に'obj'に束縛 クラス関連 クラス構文だけでなく、コンストラクタ関数でのインスタンス生成も理解しておく必要があります。 特にコンストラクタ関数を用いた方法は見落としがちな部分だと思うので、しっかり理解した上で試験に臨みましょう。 // クラス構文 class Animal { constructor(name) { this.name = name; } hello() { console.log(`this is ${this.name}`); } } class Bird extends Animal { constructor(name, action) { super(name); this.action = action; } hello() { console.log(`${this.name} can ${this.action}`); } } const animal = new Animal('Animal'); animal.hello(); // this is Animal const bird = new Bird('bird', 'fly'); bird.hello(); // bird can fly // コンストラクタ関数での書き換え function Animal(name) { this.name = name; } // helloメソッドをAnimalクラスのprototypeへ登録 Animal.prototype.hello = function() { console.log(`this is ${this.name}`); } function Bird(name, action) { Animal.call(this, name); // Animalクラスのコンストラクタを、thisを束縛しつつ呼び出す this.action = action; } // BirdクラスのprototypeにAnimalクラスのプロトタイプを割り当て Bird.prototype = Object.create(Animal.prototype); const animal = new Animal('Animal'); animal.hello(); // this is Animal const bird = new Bird('bird', 'fly'); bird.hello(); // this is bird // Birdクラスのhelloメソッドを上書き Bird.prototype.hello = function() { console.log(`${this.name} can ${this.action}`); } bird.hello(); // bird can fly 非同期プログラミング Promise ここはLWCでも使用頻度が高い部分ですが、油断は禁物です。 以下のようなチェーンや、setTimeOut() / setInterval()と複合したコード内で何が起こっているのか理解を求められます。 以下は最低限把握しておく必要があると感じた点です。 Promiseには3つの状態がある 待機 (pending): 初期状態 履行 (fulfilled): 処理が成功して完了 拒否 (rejected): 処理失敗 ※ 決定 (settled) は、fulfilledとrejectedであることを示す単なる呼び方で、settledという状態はない then() / catch() / finally()は全てプロミスを返す then() / catch() / finally()は全てコールバック関数を引数に取る → ただの引数を渡しても機能せず、引数を使用する際はコールバック関数の引数に指定する ※finally()は引数を受け付けないので注意する // Promiseチェーン const sleep = time => { return new Promise((resolve, reject) => { setTimeout(() => { console.log('called'); resolve('done'); }, time) }) } sleep(1000) .then(data => { console.log(data); return sleep(1000) }).then(data => { console.log(data); return sleep(1000) }).then(data => { console.log(data); return sleep(1000) }).finally(() => { console.log('finally'); }) async / await そんなに深堀りはされなかった印象です。 asyncが付与された関数・メソッドはプロミスを返す async functionでのみawaitが使用でき、プロミスの解決を待機する const sleep = time => { return new Promise((resolve, reject) => { setTimeout(() => { console.log('called'); resolve('done'); }, time) }) } async function callSleep() { const a = await sleep(1000); return a; } callSleep(); おわりに 取り留めのない内容になってしまった感は否めませんが、本記事でJavaScriptへの理解が少しでも深まっていれば幸いです。 最後までご覧下さりありがとうございました!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Ajaxのアクセス先をプロキシする際には、レスポンスヘッダを書き換えよ

JavaScriptでコールするAPIの中身を書き換えて表示を確認したいとき、Charlesでプロキシしてやると便利だ。 ただし、APIのドメインがウェブサイトと違うなど、オリジンが違う場合にはレスポンスヘッダを書き換えてやる必要がある。 でないと、CORSエラーが出てJavaScriptがアクセスできない。 具体的には、Access-Control-Allow-Origin:*を追加する。アクセス許可するオリジンを指定するヘッダだ。 こちらの記事が端的にまとまっていて良い。 Charlesで本番のAPIレスポンスを書き換える(SSL,CORS対応版) だが、これだけではCORSエラーが消えなくて困った。 よく見るとこんなエラー文言がコンソールに出ていた。 Request header field content-type is not allowed by Access-Control-Allow-Headers in preflight response. CORSなAPIアクセスの場合、ブラウザは予めプリフライトリクエストと呼ばれるリクエストを飛ばして、正しくCORSできるかどうか確認する。 その際、リクエストヘッダーに含まれるContent-Typeが、レスポンスヘッダーのAccess-Control-Allow-Headersで許可されている必要があるらしい。 Access-Control-Allow-Origin:*だけではダメだったのだ。 Access-Control-Allow-Headers:Content-Typeも追加しよう。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

5行のHTMLで15パズル作ってみた

概要 HTMLとJavaScriptを用い,「15パズルを実装する」というお題でコードゴルフ(ショートコーディング)をしてみました. 15パズルとは 15パズルは、スライディングブロックパズル(Sliding puzzle)のひとつである。4×4のボードの上に4×4-1すなわち15枚の駒があり、1駒ぶんの空きを利用して駒をスライドし、駒を目的の配置にする。(Wikipediaより) 要するに数字を動かして順番にそろえるコレです. レギュレーション 1行79文字 全角文字は1つにつき2文字とカウントする 基本的には,2ちゃんねるで行われていた「7行プログラミング」に準ずる形で設定しています. 遊び方 キーボードの矢印キーで,空きマスに隣接している数字を指定した方向に動かします. 数字の配置が のようになればゲームクリア. 実行環境 言語 : HTML, JavaScript 動作ブラウザ : Google Chrome, Microsoft Edge 他ブラウザでの動作確認はぶっちゃけめんどくさくてやっておりません.情報求む. 完成コード <body id=D onKeyDown=F(event.which-37) onLoad='A=[];g=f=0;for(i=16;i--;A.push(i)) ;s="①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮ ";F=(K)=>{if(!f&&0<=K&&K<4){a=A.indexOf(15);[ M,N]=K%2?[--K?a<12:a>3,a+~-K*4]:[(a+!!K)%4,a+K-1];M&&([A[a],A[N]]=[A[N],15]);S="" ;for(k=16;k--;S+=s[A[k]]+(k%4?"":"<br>"));if(g)for(f=1,r=16;--r;)f&=(A[r-1]>A[r]) }D.innerHTML=S+(f?"Win":"")};for(j=999;j--;)F(4*Math.random()|0);g=1'> 418バイト.スクリプト本体は全てonLoad属性にぶっこんでいます. 解説 スクリプト本体をonLoad属性から出して,コードに適宜改行,スペースとコメントなどを挟んだものがこちらになります. <body id=D onKeyDown=F(event.which-37)><script> // A : 盤面配列 0~15の数値を格納 // 0~14 が丸数字 ①~⑮ に対応,15 は空きマス A = []; // g : ゲーム中か(初期化中でないか)否かのフラグ // f : ゲームクリア判定のフラグ g = f = 0; for(i = 16; i--; A.push(i)); // 盤面 A に 0~15 の数値を逆順で格納 s = "①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮ "; // s : 盤面表示用丸数字テキスト // F : キー入力を受け取り,盤面を更新し,ブラウザに描写する関数 F = (K) => { if(!f && 0 <= K && K < 4){ // 未クリア & 入力されたキーが矢印キーならば a = A.indexOf(15); // a : 空きマスの位置 // M : 入力した方向に数字が動かせるかのフラグ // N : 動く対象の数字の位置 [M, N] = K%2 ? [--K ? a<12 : a>3, a+~-K*4] : [(a+!!K)%4, a+K-1]; M && ([A[a], A[N]] = [A[N], 15]); // 空きマスと数字の位置を交換 S = ""; // S : ブラウザに表示するテキスト 盤面その他を格納 for(k = 16; k--; S += s[A[k]] + (k%4 ? "" : "<br>")); // 盤面を格納 if(g){ // ゲーム中ならば for(f = 1, r = 16; --r;){ f &= (A[r-1] > A[r]); // クリア判定を行い,f を更新 } } } // ブラウザに盤面を表示,クリアしたら "Win" の文字列も追加 D.innerHTML = S + (f ? "Win" : ""); } for(j = 999; j--;) F(4*Math.random() | 0); // 盤面初期化 g = 1; // 初期化終了,g を更新(フラグをゲーム中に設定) </script> 上から順番に見ていきましょう. <body id=D onKeyDown=F(event.which-37)> ブラウザ内でキーが押下されたとき(onKeyDown),押下されたキーのキーコード(event.which)から37を引いたものを取得して,関数Fに投げています. 矢印キーの←,↑,→,↓のキーコードがそれぞれ 37, 38, 39, 40 なので,37 を引くことで 0, 1, 2, 3 に変換し,扱いやすさ向上&コード短縮に役立てています. g = f = 0; gはゲームの最中であるか(盤面の初期化の最中ではないか)を示すフラグ,fはゲームをクリア済かを示すフラグです. どちらも0すなわちfalseで初期化しています. for(i = 16; i--; A.push(i)); 盤面配列Aに 0 から 15 までの整数を逆順で格納しています. このfor文の表記ですが,変数iの値を 16 で初期化した後に条件式内でiのデクリメントを行っています.これは,i=16から条件式がfalse,すなわちi=0になるまでiを減算し続ける,という実装であり, for(i = 15; i >= 0; i--) A.push(i); という実装と同様の動作をします. 次に,関数F(K)の内部を見ていきましょう. if(!f && 0 <= K && K < 4){ ... 先述の通り,fはゲームクリア済みか否かを示すフラグであり,0ならば未クリア,0以外ならばクリア済みであることを表します. 関数Fの引数であるKは先述した (キーコード-37) の値ですから,このif文は,ゲームが未クリア,かつ入力が矢印キーからならば(i.e. Kが 0, 1, 2, 3 のいずれかならば)実行されます. a = A.indexOf(15); [M, N] = K%2 ? [--K ? a<12 : a>3, a+~-K*4] : [(a+!!K)%4, a+K-1]; ここで出てくる変数の意味は以下の通り. a : 盤面中の空きマスのある位置(0 ~ 15 の整数) M : 矢印キー押下時に,指定された方向への数字の移動が可能かどうかのフラグ(0で移動不可能,0以外で移動可能) N : 移動可能な場合,移動する対象の数字がある場所(0 ~ 15 の整数) M, Nへの代入部は複雑なので,if文で書き換えてみます. if(K % 2){ if(--K) M = (a < 12); else M = (a > 3); N = a + ~-K * 4; }else{ M = (a + !!K) % 4; N = a + K - 1; } if文は,押下された矢印キーに応じて次のように動作します. 上下キー(K=1 or 3) : 1 -> true -> 前半ブロック実行 左右キー(K=0 or 2) : 0 -> false -> 後半ブロック実行 キー入力が上下キーの場合,さらに--Kの値,すなわち上下のどちらが入力されたかが評価され,Mの値は次のように設定されます. 上キー(K=3) : --K=2 -> true -> M = (a < 12); 空きマスの位置が最下行以外 (a < 12) のとき,数字をより上行へ移動可能 下キー(K=1) : --K=0 -> false -> M = (a > 3); 空きマスの位置最上行以外 (a > 3) のとき,数字をより下行へ移動可能 Nへの代入時における~-KはK-1と同値であり,演算子~, -の優先度が*よりも上であることから,コード短縮テクニックとして頻繁に使用されます(K+1と同値である-~Kも同様). また,Kの値は先程デクリメントした値からさらに -1 されることから,Nに代入される値は以下の通りになります. 上キー('K'=3) : ~-K=1 -> N = a+4 (空きマスの 1 行下にある数字が移動) 下キー(K=1) : ~-K=-1 -> N = a-4 (空きマスの 1 行上にある数字が移動) キー入力が左右の時は以下の通り. 右キー(K=2) : !!K=true -> !!K=1 -> M = (a+1)%4, N = a+1 空きマスが左端以外の列にあるとき,空きマスの 1 列左にある数字が移動 左キー(K=0) : !!K=false -> !!K=0 -> M = a%4, N = a-1 空きマスが右端以外の列にあるとき,空きマスの 1 列右にある数字が移動 ここでは,否定演算子!を 2 回重ねて使うことで,0ならば0,それ以外ならば1という変換を行っています. S = ""; for(k = 16; k--; S += s[A[k]] + (k%4 ? "" : "<br>")); ここは盤面のテキスト化です.ここでも先述の短縮forループを利用しています. 盤面Aのk番目の要素について,それに対応する丸数字をとってきてSに加算しています. kが 4 で割り切れる,すなわち行末であるときに改行も加算します. if(g){ for(f = 1, r = 16; --r;){ f &= (A[r-1] > A[r]); } } ゲームの最中(g==true)であれば,if文内部でクリア判定を行い,フラグfを更新します. ここでは,いったんfを1(クリア済)で初期化した後,盤面配列Aの要素が昇順で並んでいれば,ループが終わったときにもfがtrueに保たれる(otherwise false),という実装にしています. ここでも先程の短縮forループを利用していますが,条件式のデクリメントが前置されているのは,rが 0 のときにループを抜けてほしいため(r-1に負になってほしくない)です. D.innerHTML = S + (f ? "Win" : ""); 盤面をテキスト化した文字列Sをブラウザに出力します. クリアしていれば(i.e. f==true)“Win”の文字列も一緒に出力します. これで関数F(K)の定義は終了です. for(j = 999; j--;) F(4*Math.random() | 0); g = 1; 最後に,ゲームの初期化処理を行っています. Fに 0, 1, 2, 3 のいずれかの数値を引数として代入して実行する処理を 999 回繰り返しています. すなわち,「とりあえずランダムな方向に数字を(最大)999 回動かす」という処理を行っています. 先程クリア判定のためにフラグgを用意しているのは,この盤面の初期化時にも関数Fを利用しているからであり,この時点でクリア判定が行われてしまうのを防ぐという目的があります. そして,初期化後にgをtrueに設定して,ゲーム中フラグを立てます. 最後に とりあえず 5 行に収めることには成功しましたが,もっとスマートな実装ができないものかという模索は今後も気が向いたときにやっていきたいなと思う所存であります. コードゴルフ楽しい!
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む