2019年1月にやったこと

年があけた。

プログラマのためのGoogle Cloud Platform入門 サービスの全体像からクラウドネイティブアプリケーション構築まで

読み終わった。この本で出てくる範囲では、AWSとの違いは

  • アカウントの下にプロジェクトの概念があること
    • やーめた、で全部消せて便利
  • IAMじゃなくてプロジェクトに対してAPIを有効化するというやり方なこと(多分他にもある気がするが)
  • Webからコンソールでだいたいゴニョゴニョできる
    • AWS Systems Managerと同じようなものなのかはよくわかっていない
    • Cloud Shellがどこで動いてて何に触れるのか、みたいなことが理解できてない
  • DynamoDBっぽいやつに親子の概念がある

くらいかなあと思った。サクサク進むしとりあえずデプロイするというところまでではまとまって良かった。

改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで

最近JavaScriptをよく書きなぐるのだが(主にChrome拡張で)あまりにも雰囲気で書いているのでいい加減体系的に学ぼうと思って読んだ。 面白かった。プログラミングの勉強って面白いなって久しぶりに思った。最近仕事でプログラミングをしていない。

第1級関数についてようやく理解した気がする。なぜGolangチュートリアルをやったのに理解していないのか。

後半のDOMいじりはリファレンス感があったので結構ざっくり読んだ。

しかし私の書くChrome拡張はだいたいどこかのWebページの構造に依存しているのであまり真面目に作る気持ちになれないという問題はある。本当はE2Eテストを自動化したい。HeadlessなChromeはextensionをサポートしていないとのことなので困っている。まあコンテンツで完結するやつはHeadlessなChromeスクリプトだけ叩けばいいような気もするけど。

Release It! 本番用ソフトウェア製品の設計とデプロイのために

この本を読まないといけないらしいのでせっかくなので社内で読書会をやってみた。いわゆる技術の本はわかるまで読めばわかるがこの手の本は人と読んだ方が楽しい気がするな。 まだ2章までなのでここからが本番な感じ。読書会て参加したことなかったのに企画をしてしまった。 会社ならいいけど読書会って通うのめんどくさくて参加できない。Webで読書会企画するプラットフォームとかあったらいいのかな。一緒にこの本やっていこうぜ!みたいな。本に対するメーリングリストの集合体でもいいんだけども。

情熱プログラマー ソフトウェア開発者の幸せな生き方

最近よく俺はなんなんだという気持ちになっているので読んでいる。半分くらい読んだ。モチベーションが下がっている時に読むと良い。楽しくて厳しい方向に進むぞ。

英語

Englishbellを43レッスン受講した。18時間くらい。ステージ7まで行ったが正直飽きてきてしまった。雑談がしたいが雑談をするならDMMに変えたい。 あと5ステージだがおそらく1年弱かかる気がする。どうしようか。

あとはEnglishbell用にしょうもないChrome拡張を作った。

inabajunmr.hatenablog.com

あとはTEDを見る活動を始めた。なんだかんだ英語力は上がっているようで初見で5〜8割くらいは理解できる気がするので普通に喋っている内容をある程度楽しめるので良さそう。

書いた記事

re:invent2018がらみの諸々を書いていた。書いていましたよ。 あとはQiitaにどうでもいいようなことをいくつか。

これからやること

  • 既存のChrome拡張を書き直す
    • せっかくJavaScript学んだので
      • でもこれはやらないかもしれん・・・
  • プログラミングコンテスト攻略のためのアルゴリズムとデータ構造
    • いい加減この手のプログラミングが弱いという気持ちで暮らすのは嫌なのでいい加減なんとかする
      • ポチった
  • 基礎から学ぶ Vue.js
    • 学ぼう
  • ElectronかWebアプリ(サーバなし)でNature RemoのPC用クライアントを作る
    • なぜか俺は音声やスマホよりもPCで操作したい時がたまにある
      • あとはSPAとJSの学習用に
  • lorcaでtreviewのアプリを作る
    • これは気が向いたら
  • Goならわかるシステムプログラミング
  • 英語
  • Release It!
  • ここ最近ほとんど業務でプログラミングをしなくなって、調整とかレビューとかばっかしてるがかなり雰囲気でやってるので、マネジメント系の本を読もうとしている
    • なにがいいのかよくわからん

ここ最近いろいろ考えていたがおれはまだエンジニアリングをやりたいのでエンジニアリングをやるぞという意思を明確にした。楽しくて厳しい環境を探す。

「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」を読んでいる④

6章まで読んだ。知らない文法だけメモ。DOMの操作はリファレンス的なところはざっくり読んだ。

「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」を読んでいる① - チョキチョキかにさん

「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」を読んでいる② - チョキチョキかにさん

「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」を読んでいる③ - チョキチョキかにさん

HTMLCollectionの操作

document.getElementsByTagの結果はHTMLCollectionであり、これは生きており、条件にマッチするエレメントが増えたり減ったりしたとき、コレクションの内容がリアルアイムに変わることを意味する。

https://developer.mozilla.org/ja/docs/Web/API/HTMLCollection

<ul id="a">
<li>aaa</li>
<li>bbb</li>
</ul>

<ul id="b">
</ul>
let a = document.getElementById("a");
let b = document.getElementById("b");
let lis = document.getElementsByTagName("li");

for(var i = 0; i < lis.length; i++){
  var item = lis.item(i);
  var li = document.createElement("li");
  var text = document.createTextNode(item.textContent);
  li.appendChild(text);
  b.appendChild(li);
}

このコードが無限ループするのは、bにliを追加すると、追加した要素もdocument.getElementsByTagName("li")の条件にマッチするので要素数が増えてしまうため。 document.querySelectrAllで返ってくるNodeListは静的なのでこの動作がない。NodeListが静的というわけではなく、querySelectorAllだとそう、という話。

EventListnerのthis

EventListnerのコールバックのthisは呼び出し元のelementn参照となる。Functionオブジェクトのbindメソッドを使うと、その関数内でのthisを後から設定できる。

EventListnerにコールバックではなくEventListnerオブジェクトを指定した場合はオブジェクト自体のthisとなるので、オブジェクトに定義したhandleEventメソッドからはそのオブジェクトのフィールドを参照できる。

アロー関数によるthisの束縛についてはこれがわかりやすい。 https://qiita.com/mejileben/items/69e5facdb60781927929 雑にいうと呼び出され方やなにに呼び出されたかを意識せず、宣言時のスコープでthisが決まるって感じ?ややこしい気がするな。

「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」を読んでいる③

5.5.2章まで読んだ。知らない文法だけメモ。知らない要素ばっかりになってきた。

「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」を読んでいる① - チョキチョキかにさん

「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」を読んでいる② - チョキチョキかにさん

クラス

var Class = function(){};
var c = new Class();
console.log(c);

Functionオブジェクトをクラスとして使う。

初期化

let Student = function(name, age){
  this.name = name;
  this.age = age;
  this.getName = function(){
    return this.name;
  };
};

let student = new Student("takashi", 10);
console.log(student.getName());

あくまでメソッドは関数オブジェクトのメンバなので後から追加もできる。

let Student = function(name, age){
  this.name = name;
  this.age = age;
};

let student = new Student("takashi", 10);
student.getName = function(){
  return this.name;
};

console.log(student.getName());

追加されたメソッドはインスタンスに対して追加されてるので別のStudentインスタンスにはない。

あくまでFunctionクラスなので、コンストラクタではなく関数として呼ばれてしまう可能性がある。

let Class = function(val){
        if(!(this instanceof Class)){
            return new Class(val);
      }
      this.val = val;
      this.getVal = () => val;
}

let c1 = new Class("a");
let c2 = Class("b"); // コンストラクタを呼び出せていないが、instanceofで判定してコンストラクタ経由でClassオブジェクトを返している。
console.log(c1.getVal());
console.log(c2.getVal());

this

thisの参照先は条件によって変わる。 コンストラクタの場合は生成したインスタンス自体。メソッドの場合はレシーバーオブジェクト。

call/apply

Functionオブジェクトのメンバで、その関数自体を呼び出す。thatに渡された値をthisとして参照できる。

prototype

メソッドはFunctionオブジェクトのフィールドであり、つまりコンストラクタを呼び出すときにFunctionオブジェクトが組み立てらる。 ので、インスタンスを作るたびに同じFunctionが毎回生成されてしまう。

同じオブジェクトの全てのインスタンスが同じprototypeへの参照を持っており、ここにFunctionオブジェクトを定義すると、Functiojnオブジェクトの初期化が無駄に複数回行われなくなる。

let Class = function(){}

Class.prototype.print = () => {
  console.log("call");
}
c1 = new Class();
c1.print();

インスタンスとprototypeに同じ名前のフィールドがあると、インスタンスが優先される。

オブジェクトリテラルでprototypeに対してメソッドを定義しするとこうなってスッキリする。

let Class = function(){}

Class.prototype = {
  print : () => console.log("call"),
  getDog : () => "dog"
}
c1 = new Class();
c1.print();
console.log(c1.getDog())

staticなプロパティ/メソッド

クラス自体に定義する。

let Class = function(){}
Class.print = () => console.log("ok");
Class.print();

プロトタイプチェーン

let Parent = function(){};
Parent.prototype = {
  print : () => console.log("Parent"),
  sleep : () => console.log("sleep")
}

let Child = function(){};
Child.prototype = new Parent(); // ChildのprototypeにParentを指定することで継承を表現
Child.prototype.print = () => console.log("Child");

c = new Child();
p = new Parent();
c.print();
p.print();
c.sleep();
p.sleep();

JavaScriptのプロトタイプチェーンはインスタンスが作成された時点で決まるので、インスタンス生成後に元クラスのprototypeを差し替えて継承元を変えても、インスタンスの挙動は変わらない。

型の判定方法

  • constructorプロパティで取得したコンストラクタと、型を比較
    • 継承してると親のコンストラクタが返って来ちゃう
  • instanceofでコンストラクタと比較
    • 継承元と比較してもtrue
  • isPrototypeOfでプロトタイプを比較

privateフィールド

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty これ使えばクロージャで表現しなくてもいいような気がする?

class命令

class Student {
  constructor(name, age){
    this.name = name;
    this.age = age;
  }
  
  print(){
    console.log(this.name + ":" + this.age)
  }
}

let takashi = new Student("takashi", 10);
let takeshi = new Student("takeshi", 80);
takashi.print();
takeshi.print();

アクセス修飾子はない。静的メソッドの宣言のためにstatic修飾子が使える。

class Super{
    constructor(val) {
    this.val = val;
  }
  print1(){console.log("Super");}
  print2(){console.log("Super");}
}

class Child extends Super{
    constructor(val1, val2) {
    super(val1);
    this.val2 = val2;
  }

    print1(){console.log("Child");}
}

let s = new Super(1);
let c = new Child(2,3);
s.print1(); // Super
s.print2(); // Super
c.print1(); // Child
c.print2(); // Super(Override)

console.log(c.val); // 2(superで親クラスのコンストラクタが呼ばれている)
console.log(c.val2); // 3

Computed property

let i = 1;
let a = {['yes' + i] : 100}
console.log(a); // {yes1: 100}

自前でのイテレーターの実装

class Test{
  constructor(max){
    this.max = max
  }
  [Symbol.iterator](){
    let value = 0;
    let that = this;
    return {
      next() {
        if (value > that.max) { // nextメソッドの内部ではthisの領域が変わってしまうので、thisではなくthatに格納した値を利用している。
          return {done:true}
        }
        return  {value:value++, done:false}
      }
    }
  }
}

let test = new Test(10);
for (let i of test){
  console.log(i);
}

Generator

yieldで値が返却(返却といっていいのか?)した後、そこで一旦停止するが次のループでまたyieldの行から処理が再開する。

function* aho(){
  let count = 0;
  while(true){
    count++
    if(count % 3 == 0){
      yield count + "!!!!!!!!!";
      continue;
    }
    if (count > 10) {break;}
    yield count;
  }
}

for(let val of aho()){
  console.log(val)
}

Proxy

オブジェクトをラップして値の参照とか更新とか初期化とか関数の呼び出しに干渉できる。

class Test {
  constructor(greeting) {
    this.greeting = greeting;
  }
}

let test = new Test("fuck");
var testProxy = new Proxy(test, {
  get: function(target, prop) {
    if(target.greeting == "fuck"){
      return "hello beautiful world";
    }
    
    return target.greeting;
  }
});
console.log(testProxy.greeting);

Testクラスのオブジェクトのgreetingフィールドがfuckだったらhello beautiful worldに差し替えてる。 用途がよくわからん。ライブラリのHTTPクライアントに呼び出し元のログの機構を組み込みたい時とかかな。

「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」を読んでいる②

4章まで読んだ。知らない文法だけメモ。

「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」を読んでいる① - チョキチョキかにさん

symbol

symbolは常に一意な値を返す。enum的に使う。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Symbol

const A = Symbol();
const B = Symbol();
A === A // true
A === B // false

Array

リテラルで初期化できる配列はArrayオブジェクト。

let array = new Array(1,2,3);

forEach

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

let array = [1,2,3];
array.forEach(function(value, index, array){
        console.log(index + ":" + value)
});

このfunctionキーワードはなんなのだろう。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions_and_function_scope

なるほど関数式。

要するに関数オブジェクトが生成されてforEachで一個ずつキックしてる感じか。Lambda式のあれみたいな感じか。

map

let array1 = [1,2,3];
let array2 = array1.map(function(value){
    return value + 1;
});
console.log(array2); // [2,3,4]

returnの値で新しい配列ができる。

some

let array = [1,2,3];
let result = array.some(function(value){
  return value === 4;
});

console.log(result)

result = array.some(function(value){
  return value === 3;
});

console.log(result)

どれかマッチしたかどうかの判定って感じ。

filter

コールバックでtrueが返った要素だけの配列を返す。

sort

let array = ["aa", "a", "aaa"];
let value = array.sort(function(x,y){
  return x.length - y.length;
})

console.log(value);

文字列でソート。

Map

  • オブジェクトと違って文字列以外をキーにできる。
  • 初期化時は要素が空。
  • Mapのキーの場合のみNaN===NaNがtrue。

キーを参照型にする場合、参照が同じじゃないとMapから値を引けない。(要するに===の結果がどうなるか。) Equals的なものはないのかな。

Set

まあなんかSetって感じ。

正規表現

let val = "1234-5678-9999";
let result = val.match(/[0-9]+/g);
console.log(result);

for(let i = 0; i < result.length; i++){
  console.log(result[i]);
}

resultにはマッチした文字列は配列で格納される。この場合gスイッチがついてるので複数マッチしてる。

マッチしてるかどうか?はRegexp.testで確認できる。

console.log(/[0-9]+/.test("abc")); // false
console.log(/[0-9]+/.test("123")); // true

マッチしてるとは?が混乱するがString.matchの結果が1件以上あるかと同義だと思えばしっくりきそう。

置換はString.replaceでできる。後方参照も使える。

Object

Objectは全てのオブジェクトの基底オブジェクト。 ここでいうオブジェクトをクラスと言っても間違いではないのだろうか。

assign

let a = {a:1, b:1};
let b = {c:2};
console.log(Object.assign({}, a, b)); // {a: 1, b: 1, c: 2}

assignの第一引数に以降のオブジェクトがマージされる。戻り値も同様の値。破壊的。

Imutable

let obj = {a:1, b:2};
Object.preventExtensions(obj); // プロパティ追加不可
Object.seal(obj); // プロパティ削除不可
Object.freeze(obj); // プロパティ変更不可

ただしstrictモードでのみ有効。

関数

関数はデフォルトでundefinedを返す。returnがあればその値を返す。

アロー関数

関数リテラルをすっきり表現できるやつという理解でいいのだろうか。

let func = (a,b) => a+b;
let val = func(1, 2);
console.log(val); // 3

関数を複数行書きたければ中括弧でくくって戻り値はreturnで返す。

function命令

function命令はコンパイル時に解析されてるので、宣言より前に呼び出せる。リテラルで初期化して値に格納する場合はあくまで値なので、その値が初期化される前に呼び出すことできない。

スコープ

変数の巻き上げ

let value = "global";
function f(){
  console.log(value); // ここでundefinedでエラー
  let value = "local";
  console.log(value);
}
f();

f関数内でのvalueの定義がなければエラーにならない。ローカル変数そのものは関数全体で有効だが、最初の出力ではまだ初期化されていないため。

ブロックスコープ

letで宣言された変数はブロックスコープになる。

let a = 1;
{    
  console.log(a);
  let a = 2;
}

巻き上げのルールは同様なのでこの場合はエラーになる。

仮引数の数

引数の数をチェックしない。足りない分はundefinedになる。

function test(a,b,c){
  console.log(a);
  console.log(b);
  console.log(c);
}

test(1); // 1, undefined, undefined

逆に仮引数がなくても引数を受け取れる。arguments経由で参照する。

引数のデフォルト

function test(a = 1){
  console.log(a);
}

test(); // 1
test(2); // 2

デフォルトは明示的に値が渡されたなかったか、undefinedが渡された場合にのみ適用される。

デフォルトがある値は後ろに宣言しないと、呼び出しが変な感じになる。(明示的にundefinedを渡してデフォルトを表現する感じになる)

// TODO オプションが複数ある場合はどうすればいいいんだろう。

必須の引数を表現

デフォルト値に例外がスローされる関数を指定しとくと必須を表現できる。めんどくさい気がしなくもない。

可変長引数

function test(...nums){
  console.log(nums);
  for(let val in nums){
    console.log(val);
  }
}
test(1,2,3);

numsは[1,2,3]になる。

function test(a, ...nums){
  console.log(nums);
  for(let val in nums){
    console.log(val);
  }
}
test(1,2,3);

この場合a=1,num=[2,3]になる。

...演算子

function test(a,b,c,d) {
  console.log(a);
  console.log(b);
  console.log(c);
  console.log(d);
}

test([1,2,3,4]); // aに配列が格納され、bcdはundefined。
test(...[1,2,3,4]); // abcdそれぞれに1,2,3,4が代入

名前付き引数

function test({a = 1, b = 2}){
  console.log(a);
  console.log(b);
}

test({a:3, b:4});

デフォルトはなくても良い。どっちかっていうとオブジェクトを渡された時それぞれのプロパティに分解する機能という理解で良さそう。

クロージャ

関数オブジェクトが参照している変数が、関数の参照が残っていると変数も確保されたままになることを利用した仕組み?

function test(arg){
    let val = arg;
    return () => ++val;
}

let a1 = test(1);
console.log(a1()); // a1の関数は参照が残る 2
console.log(a1()); // a1のスコープにあるvalも保持される 3
console.log(a1()); // なので関数が呼ばれるたびにvalのが値が増える 4

用途がわかってない。

http://d.hatena.ne.jp/artgear/20120115/1326635158

なるほど? パフォーマンスがシビアじゃない場合使わないやつくらいの認識でいいんだろか?

クラウドで同期できるメモ用のコマンドが欲しい

ざっくりイメージ

$ memo save -t ted https://www.youtube.com/watch?v=o_XVt5rdpFY
$ memo show -t ted
https://www.youtube.com/watch?v=o_XVt5rdpFY

別にtrelloでも良さそう感は否めない

「改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで」を読んでいる①

いい加減多少まともなJSをかけるようになりたい感じがあるので読んでいる。 知らない文法だけメモ。2章まで読んだ。

Template Strings

let name = "jun";
let msg = `hello $name`;

オブジェクト

オブジェクトと連想配列は、文脈で使い分けられてるが同じものを刺している。 メソッドは関数が格納されたプロパティのことで、あくまでプロパティ。

インクリメント/デクリメント演算子

a = 1; b = 1;
a++; // 1
1
++b; // 2

この時点で変数に格納されてるのはaもbも1。

分割代入

配列

let array = [1,2,3];
let [x,y,z] = array;

x,y,zには1,2,3が代入される。

let array = [1,2,3];
let [x] = array;

xには1が代入される。

let array = [1,2,3];
let [x,...y] = array;

xには1が代入される。 yには[2,3]が代入される。

オブジェクト

let target = {a:1, b:2, c:3};
let {a, b} = target;
console.log(a); // 1
console.log(b); // 2

cは無視される。

let target = {a:1, b:2, c:{c2:3}};
let {a, b, c, c:{c2}} = target;
console.log(a); // 1
console.log(b); // 2
console.log(c); // {c2:3}
console.log(c2); // 3

子要素はこんな感じ。

delete演算子

let array = [1,2,3];
console.log(array); // [1, 2, 3]
delete(array[0]);
console.log(array); // [empty, 2, 3]

オブジェクトのプロパティも削除できる。参照が消えるが参照先のオブジェクト自体は消えない。

typeof

データ型を表す文字列を返す。配列やオブジェクトは"object"になるのでどのオブジェクトかはわからない。

for...in

let obj = {a:1, b:2}
for(let key in obj){
        console.log(key + ":" + obj[key])
}

配列の全要素にアクセスするときはlengthを格納したほうがいい

毎回プロパティにアクセスすると性能が劣化する。

for...of

let array = [1,2,3];
for(let val of array){
        console.log(val);
}

ラベル構文

test:
do{
        console.log("1")
        while(true){
                console.log("2")
            break test;
      }
      console.log("3")
}while(false)

1,2が出力される。 ただのbreakだと1,2,3が出力。

例外

try...catch...finally

try{
  let i = 1/j;
}catch(e){
  console.log(e.message); // j is not defined
}finally{
  console.log("FINALLY");
}

throw

try{
  console.log("try1");
  throw new Error("error msg");
  console.log("try2"); // 出力されない
}catch(e){
  console.log(e.message); // error msg 
}finally{
  console.log("FINALLY");
}