RubyのClassクラスについてとか、クラスを知るためのメソッドとか、あれこれ(メモ)
Rubyで
MyClass.class # => Class
MyClass.class.class # => Class
という結果に Σ(・∀・;) となったので調べた。
(.classはオブジェクトが定義されたクラス名を返す。)
まとめ
Rubyでは、定義されたクラスは全て、Classクラスのインスタンスとなる。
Rubyでは、扱われる全ての要素はオブジェクトで(何らかのクラスのインスタンスで)、Objectクラスのインスタンスメソッドを継承している。(Object#classとか)
どうやら、MyClass.classで返る"Class"も、クラスであり、オブジェクトであり、Classクラスのインスタンスとして扱われるため、その結果、MyClass.class.class #=> Class が返るらしい。(難しいなぁ。考え方合ってるのかなぁ。。)
やってみよう!
StringやArrayなどの組み込みクラスも、自分で定義したMyClassも、.classを実行するとClassが返ってくる。
Rubyで扱う全ての値はオブジェクトなので、Objectクラスが持つインスタンスメソッドを継承している。あるクラスが持つインスタンスメソッドを見たいときは、instance_methodsを使う。(↓こんな感じ。)
MyClass.classが返すのは、Classクラスというオブジェクトである。
Classクラスは"クラス"の一つなので、オブジェクトであり、また、Classクラスのインスタンスであることから、MyClass.class.class #=> Class という結果になるみたい。
ちなみに、あるクラスがどんなクラスやモジュールを継承したりインクルードしているかを見るにはancestorsを使う。
出力結果の、配列の順番は、[クラス自身、親クラス、親の親クラス..]となる。クラス名の間にインクルードしているモジュール名がちょこちょこ入ってくる。
実行結果。
(Rubyで扱う全ての値はオブジェクトなので、ClassクラスもObjectクラスを継承していることがわかる。)
おしまい。m(__)m
emacs key bindingメモ
キーバインドのデフォルトで
C-h がHELPの設定になっていたので、 ~/.emacs.d/init.el ファイルに下記マクロを追加。シンタックスはemacs lisp.
(keyboard-translate ?\C-h ?\C-?)
Function: keyboard-translate from to
この関数は、文字コードfromを文字コードtoに変換するように keyboard-translate-tableを変更する。 必要ならばキーボード変換表を作成する。
画面操作(ファイル開閉、emacsプロセスの開閉、画面分割と移動、画面削除、ミニバッファから離れる)
- C-x C-c KILL TASK
- C-z SUSPEND TASK (fg → foreground)
- C-x C-f OPEN FILE
- C-x C-s SAVE FILE
- C-x 2 split-window-below
- C-x 3 split-window-right
- C-x o SELECT ANOTHER WINDOW
- C-x 0 DELETE SELECTED WINDOW
- C-] KILL MINIBUFFER
エディタの移動(上下左右の移動)
- C-p UP
- C-n DOWN
- C-b BACK
- C-f FORWARD
- C-a GO TO BEGINNING OF LINE
- C-e GO TO END OF LINE
- C-o OPEN LINE
- M-v PAGEUP
- C-v PAGEDOWN
- M->(Shift + .) Move to the END of the buffer
- M-<(Shift + ,) Move to the TOP of the buffer
エディタの操作(文字の削除、行の削除、選択範囲の削除、やり直し)
- C-h BACKSPACE
- C-d KILL FORWARD CHARACTER
- C-k KILL LINE
- C-w KILL THE REGION(バッファに保存される)
- C-_ UNDO
コピペしたいときのステップ
- C+space key(Mark Set)
- M+w(copy)
- C+y(paste)
検索
- C-r SEARCH
置換
- M+%(Shift+5)
- 置換したいテキスト入力、RET
- 新しいテキスト入力、RET
- ! (to replace all remaining occurrences without asking again.)
GNU Emacs Manual: Query Replace
一括インデント
- C+space keyで範囲選択
- CM+\
一括コメントアウト
- C+space keyで範囲選択
- M+;
操作の解除
- C+g 実行中の全ての操作をキャンセル
おわり
JavaScript 関数のカリー化と部分適用
引数を複数とる関数から、いくつかの引数を固定値で束縛した新たな関数を生成する。これにより、関数を使うたびに同じ値の引数を入力する手間が省け、見た目も簡潔なプログラムになる。
カリー化とは、複数の引数を取る関数を、1つの引数のみを取る関数のチェーンに変換する処理のこと。
みてみよう!
部分適用とは、複数の引数を取る関数を、それより少ない数の引数を取る関数に変換し、除外された引数には最初から値を指定しておく、という処理のこと。
関数に対して複数の引数を部分的に適用し、残りの引数で構成される関数を新たに作成する。
みてみよう!
※bind()メソッドは呼び出されたときに新しい関数を生成する。第一引数は新しい関数のthisキーワードにセットされる。第二引数以降は、ターゲット関数の引数として、第一引数から順に与えられる。
JavaScriptのthis
jsのthisは、ある関数が呼び出されたときに、その関数を格納していたObjectを指す。
関数を単にfunc();という形で単体で実行した場合、thisにはwindowが入る。
new演算子のthis
jsのnewは任意の関数と一緒に呼び出すことができる。
var x = new func();
上の例では、まずnewで新しい空のオブジェクト{}が生成され、次に関数func()が呼び出される。このとき関数func内のthisには新しく生成された空のオブジェクトが渡され、関数実行後、生成されたオブジェクトがnewの実行結果として変数xに代入される。
JavaScriptのプロトタイプベースのオブジェクト指向について、調べたこと
jsは(ES6より前は)クラスを持たないオブジェクト指向言語である。クラスの代わりに、プロトタイプというプロパティを作り、そのプロパティを複数のインスタンスで共有する。そのためプロトタイプベースのオブジェクト指向言語といわれている。
jsの全てのオブジェクト(関数やプロパティの集合)は、__proto__プロパティに「継承したオブジェクト」のメモリアドレスを格納できる。
jsの全てのオブジェクトは、Object.prototypeを継承している。そのため、__defineSetter__, __defineGetter__, toString, hasOwnPropertyなどのメソッドをデフォルトで使うことができる。 下記はコンソールログでオブジェクトを生成し、継承元のObject.prototypeを表示している。
コンストラクタ関数とnew演算子を使ったオブジェクト生成の例
js create object with new Object()
生成したオブジェクトの中身をコンソールで見てみよう!
chromeのコンソールログでまったく同じコードを入力する。
コンストラクタPersonから生成したperson1は、name, a, __proto__の3つのプロパティを持つ。__proto__プロパティには、コンストラクタ関数Personのprototypeのメモリアドレスを格納する。このメモリアドレスを元に、person1はコンストラクタ関数が持つoutputName()を使用することができる。
図で描くとこんな感じ。person1の__proto__にはPerson.prototypeのメモリアドレスが格納されており、Person.prototypeのプロパティの参照が可能である。
一方、person2が持つプロパティはnameと__proto__のみである。person2.aが定義されていない場合は、継承元である上位のPerson.prototypeを探索しに行く。もし見つからなければ最上位の Object.prototype までプロパティを探索しにいく。
オブジェクトの継承過程をたどる
Personコンストラクタから生成したオブジェクトperson1は、コンストラクタ関数とは別のメモリに格納される。オブジェクトによって、プロトタイプチェーンが異なる。
オブジェクトperson1は、下記のようになる。
person1 < Person < Object < null (上位の継承オブジェクトがない)
コンストラクタPersonは、下記のようになる。
Person < Empty < Object < null (上位の継承オブジェクトがない)
コンソールで見てみよう。
function Empty()のプロトタイプにはapplyやcallメソッドが定義されている。
Javascriptでclosureと、applyメソッド、callメソッドを使う
jsが持つ関数スコープを利用してクロージャー(関数閉包)を書くことができる。
上記の例では、関数countの中のローカル変数iを参照できるのは、無名関数が入っている変数xを実行したときのみである。変数iをグローバル変数にすると他の関数からの参照が可能になり、意図せずに値を変更してしまう可能性がある。
jsの全ての関数は組み込み関数Functionを継承しており、組み込み関数Functionが持つapplyメソッド、callメソッドも継承している。
callメソッド:現在のオブジェクトが持っていないメソッドを適用する。
applyメソッド:callメソッドと同じように現在のオブジェクトの代わりに、他のオブジェクトのメソッドを適用できる。引数に可変長の配列をひとつとる点がcallと異なる。以下のような感じ。
Javascriptのスコープ(関数、グローバル、ES6はブロック)と巻き上げについて
jsのローカルスコープは関数内のみを参照できることであり、グローバルスコープはscriptのどこからでも参照できることを指す。ローカルスコープを持つ変数をローカル変数、グローバルスコープを持つ変数をグローバル変数という。
スコープは変数が定義された位置で決まり、関数の外で定義されればグローバル変数、関数の中で定義されればローカル変数となる。
- 関数の外でグローバル変数を定義し、中でローカル変数を定義できる。関数内でもvarをつけなければグローバル変数を定義できる。
- 変数の巻き上げ(hoisting)で、グローバル変数への参照を、ローカル変数への参照へスイッチできる。
jsでは、関数内のどこからでもローカル変数を定義できるが、関数内のどこで定義されても、その関数内の先頭で定義されたことになる。
上記のような結果になるのは、関数の先頭で、var global;という中身のない変数が定義され、globalという名前空間がローカルスコープを参照するようになったためである。=>変数定義は必ず先頭で行うこと、でないとローカル変数を参照しているかグローバル変数を参照しているかわからなくなります。
- ブロックスコープはES6からサポートしている。
ECMAScript6より前の仕様では、ブロックスコープを採用していなかった。
ES6以降はletを使うと、ブロックスコープを作れるでござる。
ES 6で開発するにはBabelか、
気軽に試したかったら、fiddleで試してみてください。