Text
[GAS] 配列の次元数を調べるスニペット
概要
1 次元配列か 2 次元配列かを判定したいなー、そうそう、 array[0].length の 暗黙の型変換で調べれば一発だったよね、って記憶違いをしていたので、メモ。
まとめとコード
テストはミニマムでやりましょう。
function myFunction() { const a1 = [1, 2, 3]; const a2 = [[1], [2], [3]]; console.log(a1[0].length); // undefined console.log(a2[0].length); // 1 }
うんうん、やっぱりそうだよねって、本番の 1 次元配列のコードだと、 false が返ってこない。 違うのは、配列の中身が数値型か文字列型かってとこくらい。 文字列でも一緒だろうけど、念の為にテストを。
function myFunction() { const a1 = ['あ', 'い', 'う']; const a2 = [['あ'], ['い'], ['う']]; console.log(a1[0].length); // 1 console.log(a2[0].length); // 1 }
なんか、思ってたんと違う...。 気を取り直して、テストを。
function myFunction() { const a1 = ['あ', 'い', 'う']; console.log(a1[0]); // あ console.log(a1[0].length); // 1 console.log(a1[0][0]); // あ console.log(a1[0][0].length); // 1 console.log(a1[0][0][0]); // あ console.log(a1[0][0][0].length); // 1 console.log(a1[0][0][0][0]); // あ console.log(a1[0][0][0][0].length); // 1 console.log(a1[0][0][0][0][0]); // あ console.log(a1[0][0][0][0][0].length); // 1 }
なるほど、文字列「あ」は、どこまで次元を掘り下げても「あ」であり続けられることが推測できるな。 違う、欲しいのはそこじゃない。 アプローチを変えよう、今回の配列だと、純粋な文字列「あ」になった時点、すなわち配列でなくなった時点が確認できればいい。 typeof 演算子を使ったアプローチに切り替えました。
function myFunction() { const a1 = ['あ', 'い', 'う']; const a2 = [['あ'], ['い'], ['う']]; console.log(numDimensions_(a1)); // 1 console.log(numDimensions_(a2)); // 2 } function numDimensions_(array) { let count = 0; while (typeof array === 'object') { count++; array = array[0]; } return count; }
これでバッチリ。 ただ、これだと、次元を掘り下げていった場合の 1 番目の要素でしか判定ができない。実用では問題ないけど、関数名に numDimensions とつけてしまった以上、引き下がれない。 きっとあれだ、判定後の配列要素だけを filter して、それを 1 次元下げたものに map してやれば問題ないよね。 空の要素だけになった場合の対策も入れておけば完璧かな。
function myFunction() { const a1 = [['あ'], [[[['い']]]], [['う']]]; console.log(numDimensions_(a1)); // 4 } function numDimensions_(array) { let count = 0; while (typeof array === 'object') { count++; if (!array.length) break; array = array .filter(e => typeof e[0] === 'object') .map(e => e[0]); } return count; }
完璧!(たぶん
2 notes
·
View notes
Text
[GAS]csv ファイルを作成するスニペット
概要
いままで、VBA で走らせてた csv の出力ファイルを GAS で運用するにあたって、ちょっと躓いたので、メモ。 文字コードは Shift-JIS を選択していたのに、某���ずほの web サービスが読み込んでくれない。 一度ローカルで開いて保存しなおせば問題ない。 とりあえず、メモ用につぶやく。
ん、なんじゃろ。GAS で csv 形式でエクスポートしたファイルをみずほ銀行に吸わせようとするとエラーが出るけど、csv ファイルをいったん開いて保存すれば問題ない。時間あるときに���調査だな。
— etau (@etau0422)
February 22, 2021
すぐに降臨されるなにか。
文字コードとか改行コードは仕様とあってますか?
— fuji.t (@celaeno4)
February 22, 2021
やだ、イケメン。
まとめとコード
というわけで、スニペット化しちゃえば問題ないよねってことで、作ってみたよ。
/** * csv ファイルを作成する関数 * * @param {Object[][]} values - csv 化する値 * @param {string} folderId - 出力先のフォルダー ID * @param {string} fileName - csv ファイル名 * @param {string} os - 出力先の OS の指定 (Mac: OS X の場合は unix で OK) */ function createCsv_(values, folderId, fileName, os = 'unix') { const formatData = { unix: { newLine: '\n', characterCode: 'UTF-8' }, windows: { newLine: '\r\n', characterCode: 'Shift-JIS' } }; const format = formatData[os]; const data = values.join(format.newLine); const folder = DriveApp.getFolderById(folderId); const blob = Utilities.newBlob('', MimeType.CSV, fileName).setDataFromString(data, format.characterCode); folder.createFile(blob); }
Windows 以外は、第 4 引数省略して使えばいい感じ。 いやー、ありがとうございました!
参照人
fuji.t - @celaeno4
参照サイト
改行コードの確認
2 notes
·
View notes
Text
[GAS] 2 次元配列を転置させるワンライナーの解説
概要
ノンプロ研 の今年末大 BT 大会は、今年 4 日もあるんですが、その夜の��親会で質問を受けました。 かにみそ.gs ちゃんに見せてもらったスニペットは、偶然数日前に拾ったそれと同じで、時間あるときにやろうと思ってたやつだー!と飛びつきました。
arr[0].map((col, i) => arr.map(row => row[i]))
サクサクっと回答して、イケメン + 天才ぶりを見せつけてやろうと思いましたが、 console.log() を置く位置も定まらず...。 言い訳として、20 時からの BT 大会 (飲んでる) で、質問を受けたのは 23 時でした。 いやー、天才もイケメンもお酒には勝てないですね!
まとめとコード
というわけで解説。いつもながらコードで語っていきます。
function myFunction() { const values = [ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]; /* 元のスニペット */ // const rotated = values[0].map((_, i) => values.map(record => record[i]))); /* values[0].map((_, i) を [0, 1, 2] に置き換えたもの */ // const rotated = [0, 1, 2].map(i => values.map(record => record[i])); /* columunIndexs の別のとり方 */ const columnIndexs = [...Array(values[0].length).keys()]; // [0, 1, 2] const rotated = columnIndexs.map(columnIndex => values.map(record => record[columnIndex])); console.log(rotated); // コメントアウトしている各 rotatd は同じ値 /* 以下、各値の確認*/ values[0].map((_, i) => console.log(i)); // 0, 1, 2 values.map(record => console.log(record[0])); // 1, 4, 7 values.map(record => console.log(record[1])); // 2, 5, 8 values.map(record => console.log(record[2])); // 3, 6, 9 console.log(values.map(record => record[0])); // [1, 4, 7]: record [1, 2, 3] に対して 1, [4, 5, 6] に対して 4, [7, 8, 9] に対して 7 が返り、結果 values に対して [1, 4, 7] が返る console.log(values.map(record => record[1])); // [2, 5, 8] console.log(values.map(record => record[2])); // [3, 6, 9] }
いよーし、良い子のみんなは、完璧に理解できたかなー? 説明すると、 values[0].map((_, i) で、列数分のインデックスを配列化してあげるじゃない? それで、values.map(record => record[i]) の処理で、その各要素 [0, 1, 2] に対して、0 を持っていった場合は、values の第 1 要素 [1, 2, 3] を 1 に、第 2 要素 [4, 5, 6] を 4 に、第 3 要素 [7, 8, 9] を 7 に置き換えたものを配列化して、結果、 i が 0 の場合は values の第 1 要素 [1, 2, 3] に [1, 4, 7] が返り、i が 1 の場合は values の第 1 要素 [4, 5, 6] に [2, 5, 8] が返り、i が 2 の場合は values の第 1 要素 [7, 8, 9] に [3, 6, 9] が返ります。 いやー、夢の中でだいぶ復習しちゃった。 いい課題をありがとー!
1 note
·
View note
Text
[GAS] replace メソッドと reduce メソッド
概要
GAS活 でちらっと見つけた、配列要素から、replace メソッドをまとめてドーンと効かせるイケてるやつ!
まとめとコード
衝撃だったのは、reduce メソッドに初期値が持たせられることでした。 ここを知らなかったので、reduce メソッドの要素��、返ってくる値 (今回で言うところの初期値) と型を揃えなければ使えないと勘違いしていました。 好きだった reduce メソッドちゃんは、大好きな大本命の reduce メソッド様へ格上げと相成りました。 a → A, b → B と置換するスニペットです。
const value = 'abcabc' ; const lists = [[/a/g, 'A'], [/b/g, 'B']]; const replaced = lists.reduce((acc, list) => acc.replace(...list), value); console.log(replaced); // ABcABc
応用編で、置換元と置換先を設定してあげれば、これでさらにドカンといけますね。
const lower = 'abcdefg'; const upper = 'ABCDEFG'; const list = lower.split(''); const lists = list.map((str, i) => [new RegExp(str, 'g'), upper[i]]); const value = 'auaua-'; const replaced = lists.reduce((acc, list) => acc.replace(...list), value);
はぁ、日々是勉強っすなぁ。
参照サイト
Array.prototype.reduce() - JavaScript | MDN
0 notes
Text
[GAS] 時間差を HH:mm:ss で表示させる
概要
こんなコードを書いてたら、くのーるに、もっとサクッと書けないんですか?って煽られたので、がんばってみたよ。
const date1 = new Date('2019/09/11 16:53:12'); const date2 = new Date('2019/09/11 17:00:36'); const diffTime = new Date(Math.abs(date1.getTime() - date2.getTime())); const hours = diffTime / (1000 * 60 * 60); const minutes = (hours - Math.floor(hours)) * 60; const seconds = (minutes - Math.floor(minutes)) * 60; const padZero = (num) => String(Math.floor(num)).padStart(2,'0'); console.log(padZero(hours) + ':' + padZero(minutes) + ':' + padZero(seconds));
まとめとコード
いろいろ考えました。 formatDate メソッドで普通 HH:mm:ss って書けばいいんでしょって考えた時期が僕にもありました。 9 時間勝手に足されてね?9 時間ってあれじゃね?ぴこーん!って感じで、天才でよかったです。
const date1 = new Date('2019/09/11 16:53:12'); const date2 = new Date('2019/09/11 17:00:36'); const diffTime = new Date(Math.abs(date1.getTime() - date2.getTime())); const strDiffTime = Utilities.formatDate(diffTime, 'UTC', 'HH:mm:ss');
0 notes
Text
[GAS] 2 次元配列内の 1 次元配列をオブジェクト化した要素を持つ配列に変換し、元の配列に戻す
概要
こんな感じのスプレッドシートの値から、2 次元配列をよくとるよね。 それを行単位のオブジェクト化した配列に変換して使うことが最近多いのでスニペット化してみたよ。 ついでに、そのオブジェクトの配列から元の配列に戻すコードも書いたよ。
まとめとコード
特に注意点はないけど、もとのスプレッドシートがきっちり構造化できてないと、つらいよね。 あとあれだ、両方の配列から対象オブジェクトや配列を抜く filter メソッドもおまけしとこう!
function myFunction() { const sheet = SpreadsheetApp.getActiveSheet(); const values = sheet.getDataRange().getValues(); const objects = createObjects_(values); console.log(objects); // [ { name: 'hoge', age: 20, favorite: 'curry' }, // { name: 'fuga', age: 30, favorite: 'chocolate' }, // { name: 'piyo', age: 40, favorite: 'coffee' } ] console.log(objects.filter(object => object.name === 'fuga')[0]); // { name: 'fuga', age: 30, favorite: 'chocolate' } const newValues = createValues_(objects); console.log(newValues); // [ [ 'name', 'age', 'favorite' ], // [ 'hoge', 20, 'curry' ], // [ 'fuga', 30, 'chocolate' ], // [ 'piyo', 40, 'coffee' ] ] console.log(newValues.filter(record => record.includes('fuga'))[0]); // [ 'fuga', 30, 'chocolate' ] } function createObjects_(values) { const headers = values.shift(); const objects = []; for (const record of values) { const object = {}; for (const [i, header] of headers.entries()) { object[header] = record[i]; } objects.push(object); } return objects; } function createValues_(objects) { const headers = Object.keys(objects[0]); const values = [headers]; for (const object of objects) { const record = []; for (const header of headers) { record.push(object[header]); } values.push(record); } return values; }
なかなかかっこいい。
被参照サイト
[GAS]2次元配列をオブジェクトに変換する‐1日目‐ | 学習と成長のブログ
0 notes
Text
[GAS] splice メソッド
概要
こないだの記事を書いたあとに、あれ、全部 splice メソッドで書けるよね?って思って、splice メソッドまとめてみたよ。
まとめとコード
思ったより多機能というか、多機能すぎて、こりゃ混乱するな。
function myFunction() { const array = [1]; array.splice(0, 0 ,0); // [ 0, 1 ] console.log(array); array.splice(2, 0, 2, 3, 4, 5) // [ 0, 1, 2, 3, 4, 5 ] console.log(array); const array2 = [6, 7, 8, 9, 10]; array.splice(array.length, 0, ...array2); console.log(array); // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ] array.splice(6, 1, 'a'); console.log(array); // [ 0, 1, 2, 3, 4, 5, 'a', 7, 8, 9, 10 ] const array3 = ['b', 'c', 'd']; array.splice(7, array3.length, ...array3); console.log(array); // [ 0, 1, 2, 3, 4, 5, 'a', 'b', 'c', 'd', 10 ] array.splice(9, 2); console.log(array); // [ 0, 1, 2, 3, 4, 5, 'a', 'b', 'c' ] array.splice(6); console.log(array); // [ 0, 1, 2, 3, 4, 5 ] array.splice(-4) console.log(array); // [ 0, 1 ] array.splice(0, 1); console.log(array); // [ 1 ] }
shift メソッドや push メソッドに置き換えられるような処理もあるけど、これ一つで全部できるんじゃないかってくらい優秀だね。
参照サイト
Array.prototype.splice() - JavaScript | MDN
1 note
·
View note
Text
[GAS] 配列内の要素から複数の要素を生成して、配列内にもどす
概要
なんか、すげー簡単そうなのにチョット詰まっちゃったので、メモとして。 日時が入力された 2 次元配列内の値を、日付と時間に分けて時間分の要素を増やすためのスクリプトです。俺得だけどごめんなーってやつだね。
まとめとコード
さてさて、いろいろと悩んだけど、この形が一番スッキリしててよかったかな。 まずは、配列バージョン。
function myFunction() { const values = [ [1, '2020/01/01 00:00:00', 'a', 'b', 'c'], [2, '2021/12/31 11:11:11', 'd', 'e', 'f'] ]; console.log(replacer_(values)); } function replacer_(values) { for (const [i, record] of values.entries()) { const [num, dateAndTime, ...others] = record; const array = spliter_(dateAndTime); values[i] = [num, ...array, ...others]; } return values; } function spliter_(dateAndTime) { return [ Utilities.formatDate(new Date(dateAndTime), 'JST', 'yyyy/MM/dd'), Utilities.formatDate(new Date(dateAndTime), 'JST', 'HH:mm') ]; }
次に、オブジェクト バージョン。
function myFunction() { const values = [ [1, '2020/01/01 00:00:00', 'a', 'b', 'c'], [2, '2021/12/31 11:11:11', 'd', 'e', 'f'] ]; console.log(replacer_(values)); } function replacer_(values) { for (const [i, record] of values.entries()) { const [num, dateAndTime, ...others] = record; const dateObj = spliter_(dateAndTime); values[i] = [num, dateObj.date, dateObj.time, ...others]; } return values; } function spliter_(dateAndTime) { return { date: Utilities.formatDate(new Date(dateAndTime), 'JST', 'yyyy/MM/dd'), time: Utilities.formatDate(new Date(dateAndTime), 'JST', 'HH:mm') }; }
投げる要素や spliter 関数の部分をいじれば、いろいろと汎用性あるんじゃないだろうか? return する要素が多い場合は、配列バージョンのが楽な感じかな~。 いつ以来だろう、このブログ書くの。
0 notes
Text
[GAS]2 次元配列の各要素を for...of 文で置換する
概要
犀のときに fof i, j で 2 次元配列の各要素に対して、replace メソッドを効かせてたのを for of 文でかっこよくできないかなと思って。 犀のときのコードはこちら。
function myFunction() { var values = [['あい', 'あか', 'あうあうあー' ]]; for (var i = 0; i < values.length; i++) { for (var j = 0; j < values[i].length; j++) { values[i][j] = values[i][j].replace(/あ/g, 'お'); } } Logger.log(values); // [[おい, おか, おうおうおー]] }
まとめとコード
まずは、そのまま for of 文に書き換えた感じ。
function myFunction() { const values = [['あい', 'あか', 'あうあうあー' ]]; for (const record of values) { for (const value of record) { value = value.replace(/あ/g, 'お'); } } console.log(values); }
この場合は「TypeError: Assignment to constant variable.」になっちゃうね。
function myFunction() { const values = [['あい', 'あか', 'あうあうあー' ]]; for (let record of values) { for (let value of record) { value = value.replace(/あ/g, 'お'); } } console.log(values); // [ [ 'あい', 'あか', 'あうあうあー' ] ] }
この場合は要素の置換はおこなわれるけど、配列を直接参照していないね。
function myFunction() { const values = [['あい', 'あか', 'あうあうあー' ]]; for (const [i, record] of values.entries()) { for (const [j, value] of record.entries()) { values[i][j] = value.replace(/あ/g, 'お'); } } console.log(values); // [ [ 'おい', 'おか', 'おうおうおー' ] ] }
これでやっと、やりたいことにたどり着いたけど、なんとも不細工。
function myFunction() { let values = [['あい', 'あか', 'あうあうあー' ]]; values = values.map(record => record.map(value => value.replace(/あ/g, 'お'))); console.log(values); // [ [ 'おい', 'おか', 'おうおうおー' ] ] }
values を let で宣言するのが嫌じゃなければ、map メソッド使ったほうがスッキリかもね。
0 notes
Text
[GAS]正規表現にマッチした一部を置換する
概要
ノンプロ研 の VBA チャンネルのお題に、巻き込まれ事故した感じで解いてみたよ。 お題は (全角) カッコ内の (全角) カンマのみ、読点 「、」に変更するというもの。 一番難しかったのは、カッコとカンマが全角であるということに気づくことでしたね。
まとめとコード
最初パッと思いついたのが正規表現だったけど、正規表現はマッチした部分をまるっと全部置換しちゃうからなぁ~って、念の為リファレンス読んだら「第二引数として関数を指定することができます」なる表記が。 replace の正規表現にマッチした部分に replace あてればいいんじゃん?! できんの?!できたー!の結果がこちらです。
function myFunction() { const text = 'A,B,C(D,E,F,G,H,I)J(K),(L,M),N(O,P,Q),R,S(T,U,V,W),X,Y,Z'; const replacer = (match) => match.replace(/,/g, '、'); let newText = text.replace(/(.*?)/g, replacer); console.log(newText); // A,B,C(D、E、F、G、H、I)J(K),(L、M),N(O、P、Q),R,S(T、U、V、W),X,Y,Z }
フラグ方式で解いたこれはおまけね。 三項演算子は正直好きじゃないです。
function myFunction() { const text = 'A,B,C(D,E,F,G,H,I),J(K),(L,M),N(O,P,Q),R,S(T,U,V,W),X,Y,Z'; let isInbracket = false; let newText = ''; for (const char of text) { if (char === '(') isInbracket = true; if (char === ')') isInbracket = false; isInbracket && char === ',' ? newText += '、': newText += char; } console.log(newText); // A,B,C(D、E、F、G、H、I)J(K),(L、M),N(O、P、Q),R,S(T、U、V、W),X,Y,Z }
意外と楽しかった。 String.prototype.replace() - JavaScript | MDN
1 note
·
View note
Text
[Python][Google Colab] Google Colaboratory の重要な設定
概要
ちょっとやる気が出てきたから、Python がんばってみる。 環境はいろいろ考えちゃうけど、ノンプログラマーなぼくらの会社では Colaboratory で走っていこうかなと。 コケたらコケた時に考えましょう。 まずは、 Colaboratory - G Suite Marketplace からインスコすんだけで、準備は完了! では、みなさん快適な Python ライフを!
まとめとコード
画像の 2 をクリックすると、「Untitled0.ipynb」ってファイルができます。 「Jupyter Notebook」と似た感じで使えるので、いいですね。正直 VS Code のが楽しいんですが、マニュアルも一緒にセットで考えた時に、テキスト枠にマークダウンでいろいろ残せちゃうのは、これまたノンプログラマーの環境に優しいなと。 それでは、Google Colaboratory でいちばん重要な設定だけおこないましょう。 画面右上、自分のアイコンの隣の [歯車アイコン (設定を開く)] - [その他] から、 この 2 箇所にチェックを入れます。 これで完了です。 みなさん��適な Python ライフを!(2 回目
0 notes
Text
[Python]タスクスケジューラーで、バッチファイルから .py ファイルを実行する
概要
Garmin Connect の Google カレンダーへの反映ができない問題に嫌気が差して、アクティビティ情報を引っこ抜いて、Google カレンダーへ反映させちゃおう!って計画は何事もなく (だいぶいろいろあったけど) 実行されたわけですが、GAS が得意のタイムトリガーみたいな自動実行をやろうと思ったところ、ちょっとつまったのでメモとして。
まとめとコード
前提として、バッチファイルは実行をさせたい .py ファイルと同階層にあり、Anaconda はパスを通した状態です。 「garmin_scheduler.py」をバッチファイルからダブルクリックで手動実行する場合は、以下の 1 行で実行されます。
python garmin_scheduler.py
が、これをタスクスケジューラーから自動実行させようとすると、うんともすんとも言いません。 これに 1 行書き足します。
cd C:\Users\etau\Documents\Python Scripts\Garmin python garmin_scheduler.py
これで、バッチファイルを叩けば .py ファイルが起動します。 これをタスクスケジューラにセットしておけば、お好みの時間やタイミングで実行されます。
参照サイト
これで解決: タスクスケジューラでバッチファイルが実行できない
0 notes
Text
[GAS][V8]ループ処理と変数・定数宣言
概要
for...of なんてのがいきなりでてきて、for...in 文含めて、const や let との絡みはどうしましょうってことで、ちょっと調べてみたよ。
まとめとコード
イテレーター以外は const でいけますね。
function myFunction() { const array = [0, 1, 2, 3, 4]; const object = {a: 0, b: 1, c: 2, d: 3, e: 4}; /* イテレーター に const は不可 TypeError: Assignment to constant variable. for (const i = 0; i < array.length; i++) { console.log(i); } */ /* 配列のイテレーターを使ったループ処理 */ for (let i = 0; i < array.length; i++) { console.log(i); } /* 配列のイテレーターを必要としないループ処理 */ for (const element of array) { console.log(element); } /* 問題なく動くが意味合いが異なるので利用しないほうがいいかなぁ~ */ for (const element in array) { console.log(element); } /* オブジェクトに for...in 文は不可 TypeError: object is not iterable for (const element of object) { console.log(element); } */ /* オブジェクトのループ処理 */ for (const element in object) { console.log(element); } }
イテレーターが必要ないところは for...of 文つかって、オブジェクトのみに for...in 文ってのをルール化すれば、スッキリするんじゃないかなぁ~?
参照サイト
for - JavaScript | MDN for...of - JavaScript | MDN for...in - JavaScript | MDN
0 notes
Text
[GAS][V8]var と let と const についての考察
概要
V8 へのバージョンアップへもだいぶなれてきた昨今 (そうでもない)、var, let, const どうしようかなと考え中。 サクッと書いたこの 2 記事。 etau the non programmer coder — [GAS][V8]let と var の違い etau the non programmer coder — [GAS][V8]const と文字列 から流れてきた、この Tweet 先のコード。
この記事はすでにV8で書かれてるね /Manage event registration with Apps Script, Google Calendar and Google Forms https://t.co/CbtKWsC3PI
— タカハシノリアキ@パーフェクトExcelVBA発売中! (@ntakahashi0505)
February 21, 2020
少しまとめてみましょう。 ...と思いましたが、 ここ に全部書いてあるので、コードで語ってみましょう。
まとめとコード
どうも JavaScript のリファレンス部分で書かれていること (を読んで俺が理解していること) と、動作が少し違う気がするんだけど、今のところはこんな感じ。
/* グローバルで宣言 */ const HOGE_0 = 'hoge0'; let fuga0 = 'fuga0'; // 現状、問題なく動きそうだが使わない var piyo0 = 'piyo0'; console.log(HOGE_0); // hoge0 console.log(fuga0); // fuga0 console.log(piyo0); // piyo0 /* 関数内で宣言 */ function myFunction() { console.log(HOGE_0); // hoge0 console.log(fuga0); // fuga0 console.log(piyo0); // piyo0 /* if ブロックで宣言 */ if (true) { const hoge1 = 'hoge1'; let fuga1 = 'fuga1' var piyo1 = 'piyo1'; console.log(hoge1); // hoge1 console.log(fuga1); // fuga1 console.log(piyo1); // piyo1 /* 再代入 */ // hoge1 = 'hoge1_2'; TypeError: Assignment to constant variable. fuga1 = 'fuga1_2'; piyo1 = 'piyo1_2'; } /* if ブロックで宣言した値の確認 */ // console.log(hoge1); ReferenceError: hoge1 is not defined // console.log(fuga1); ReferenceError: fuga1 is not defined console.log(piyo1); // piyo1_2 /* 宣言後代入しないパターンの確認 */ // const hoge2; SyntaxError: Missing initializer in const declaration let fuga2; var piyo2; if (true) { fuga2 = 'fuga2'; piyo2 = 'piyo2'; } console.log(fuga2); // fuga2 console.log(piyo2); // piyo2 }
コードの結果読み解く限り、置き換えに若干の工夫はいるものの、 var さんの存在意義がというか利用シーンがあまり思い浮かばない。 あと、最初の Tweet 先のコードは function は、const + アロー関数で全部書いてるのがなぁ、これが主流になる可能性もあるかと思うと、感覚から修正いれてかないとなぁ。 グローバルで宣言する const は、関数 (+ アロー関数) でない、値の代入だけの場合はコンスタントケースを使っ��、後はローカル含めて全部キャメルケースでいけそうなのは参考になりました。
参照サイト
V8 Runtime Overview | Apps Script | Google Developers Manage event registration with Apps Script, Google Calendar and Google Forms const - JavaScript | MDN let - JavaScript | MDN 変数名の命名規則/**ケースの使い分け - Qiita
0 notes
Text
[GAS]論理演算子 !! (論理 NOT × 2) の利用法
概要
「わっ!びっくりした!!」の「!!」のお話ではありません。 購入した 本 に書いてあったんですよ「ブール値への型変換」に !! が使えるって。 確かになんにでも、「!」さえつけちゃえば、ほしい結果と逆にはなるけどブール値へ型変換してくれるから 2 つつければ希望のブール値返ってくるよね~って読みながら、使いどころがまったく思い浮かばなかったんですけど、たまたまリファクタリングしてたコードに使えるところがあったのでメモとして。
まとめとコード
たとえば、こんなコードがあったとします。
function myFunction() { const hoge = 'fuga'; let message; /* ここから別関数にしたい */ if (hoge === 'hoge') { message = '変数の値は hoge です。処理を続けます。'; } else { // 変数の値が hoge でない場合は、処理を終了 return; } console.log(message); /* ここまで */ console.log('次の処理を実行します'); }
この if ブロックから console.log(message); を別関数として処理をさせたい場合の else 判定を食らった際の return の動きが問題です。 myFunction 内にいる場合には想定通りに処理が終了すしますが、別関数に分けた場合、別関数自体の処理は終了しますが、メインとなる myFunction は走り続けるわけです。 ここの部分のためにブール値を宣言して戻り値返すのかっこ悪くない?って考えてたら降りてきました。 まずは、思ったとおりに処理できない例です。
function myFunction() { const hoge = 'fuga'; isHoge_(hoge); console.log('次の処理を実行します'); } function isHoge_(hoge) { let message; if (hoge === 'hoge') { message = '変数の値は hoge です。処理を続けます。'; } else { // 変数の値が hoge でない場合は、処理を終了 return; } console.log(message); }
これだと、 console.log(message); は実行されませんが、myFunction 自体は走り続け console.log('次の処理を実行します'); は実行されてしまいます。 こいつを、myFunction も含めこう書き換えます。
function myFunction() { const hoge = 'fuga'; if (!isHoge_(hoge)) return; console.log('次の処理を実行します'); } function isHoge_(hoge) { let message; if (hoge === 'hoge') { message = '変数の値は hoge です。処理を続けます。'; } else { // 変数の値が hoge でない場合は、処理を終了 return; } console.log(message); return !!message; }
おわかりいただけたであろうか? ���げっぱなし (宣言だけして代入しない) スタイルからの !!message を return してる美しさ。 おかかご飯 3 杯はいけるね!(ご飯だけで食べれない派
参照サイト・本
『改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで』 - 山田 祥寛
0 notes
Text
[GAS][V8]for... of 文
概要
V8 の記事なんかをいろいろ読んでたら、ぽっとでてきました、 for...of 文。 あれ、似たようなのなかったっけ?ってふと思い出したのが、 for...in 文。 親戚の方ですかな?と思って調べてみました。
まとめとコード
構文自体はそっくりなんですが、for...of 文は反復可能 (イテラブル) なオブジェクトが定義した順序で値を反復するとのこと。 オブジェクトに対しては for...in 文じゃないと無理な感じだね、これ。
function myFunction() { const values = SpreadsheetApp.getActiveSheet().getDataRange().getValues(); for (let i = 0; i < values.length; i++) { for (let j = 0; j < values[i].length; j++) { console.log(values[i][j]); } } }
スプレッドシートから取得した値に対して、こんなふう ↑ に書いてたコードが、こんな書きかた ↓ になる日は来るのかなぁ~?
function myFunction() { const values = SpreadsheetApp.getActiveSheet().getDataRange().getValues(); for (let record of values) { for (let value of record) { console.log(value); } } }
インデックス番号使わなければ、まったく問題なさそうだもんなぁ。
参照サイト
for...of - JavaScript | MDN
0 notes
Text
[GAS][V8]Symbol オブジェクト
概要
GAS が V8 に対応したら、もう JavaScript の勉強したほうが早いんじゃないかな?という観点から早速 本 を購入。 面白そうな箇所をつまみ食いしてると、知らない子が混ざってるじゃないですか?! というわけで、早速調べてみます。
まとめとコード
なにが書かれているかわからないユニークなキーを生成してくれるところまでは理解した。 が、またしても全然わからん。コードと語り合おう。
function myFunction() { const s1 = Symbol('s'); console.log(typeof s1); // symbol console.log(s1.toString()); // Symbol(s) const s2 = Symbol('s'); console.log(s1 === s2); // false: 引数が同じでも別々に作成されたシンボルは別物 const obj = { [s1]: 'hoge', [s2]: () => console.log('fuga'), s3 : 'piyo', s4 : () => console.log('gao') }; console.log(obj[s1]); // hoge obj[s2](); // fuga console.log(obj.s3); // piyo obj.s4(); // gao for (var key in obj) { console.log(`${key}: ${obj[key]}`); // 1. s3: piyo, 2. s4: () => console.log('gao') } }
なるほどなるほど、プロパティ・メソッド名のバッティングに対応する��めに作られたのね。 あまり使い所なさそうだけど。そして for of と出会う。
参照サイト・本
『改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで』 - 山田 祥寛 Symbol - JavaScript | MDN ECMAScript6にシンボルができた理由 - Qiita
0 notes