JavaScript 文法メモ

これを読んで、脱初心者を試みる。

関数の呼び出し

thisに辞書みたいにキーを指定するとprototypeした関数が呼び出せる。

   function A(){

    }

    A.prototype.say = function(){
        console.log('Hello');
    };

    A.prototype.tell = function(){
        this["say"]();
    };

    var a = new A();
    a.tell();

prototype

function Human(name){
        this.name = name;
        this.greet = function(){ メモリ余計に食う
           console.log("Hello " + this.name);
        };
    }
    
    var mike = new Human("Mike");
    mike.greet();
    var alice = new Human("Alice");
    alice.greet();

こう書くと、greet関数がnew Human()するたびに作られるから、メモリを余計に喰う。

function Human(name){
        this.name = name;
    }
    Human.prototype.greet = function(){
        console.log("Hello " + this.name);
    };
    var mike = new Human("Mike");
    mike.greet();
    var alice = new Human("Alice");
    alice.greet();

こう書くと、greet関数が1つだけできて、使うときはその1つを参照しに行くだけとなる。

クロージャ

関数の中で関数を定義することによって、変数を外部から変更不可にしながら保持。

それぞれのオブジェクトで環境を持てるようなイメージ。

function createCounter(){
        var count = 0;
        return function(){
            count++;
            console.log(count);
        }
    }
    var counter1 = createCounter();
    counter1(); // 1
    counter1(); // 2
    counter1(); // 3
    var counter2 = createCounter();
    counter2(); // 1
    counter2(); // 2
    count = 100; 
    counter1(); // 4

オブザーバー

辞書に関数を登録しておくイメージ。

function Observer(){
        this.listeners = {};
    }

    Observer.prototype.on = function(event, func){
        if(!this.listeners[event]){
            this.listeners[event] = [];
        }
        this.listeners[event].push(func);
    };

    Observer.prototype.off = function(event, func){
        var ref = this.listeners[event], len = ref.length;
        for(var i = 0;i<len;i++){
            var listener = ref[i];
            if(listener == func){
                ref.splice(i,1);
            }
        }
    };

    Observer.prototype.trigger = function(event){
        var ref = this.listeners[event];
        for(var i=0, len=ref.length; i < len; i++){
            var listener = ref[i];
            if(typeof listener == "function") listener();
        }
    };

    var observer = new Observer();
    var greet = function(){
        console.log("Good morning");
    };
    observer.on("morning", greet);
    observer.trigger("morning");

    var sayEvening = function(){
        console.log("Good evening");
    };
    observer.on("evening", sayEvening);
    observer.trigger("evening");

this の束縛

JSでの this は、その関数の属しているオブジェクトのこと。 「関数の持ち主」のイメージ。

function Human(name){
            this.name = name;
        }
        function greet(arg1, arg2){
            console.log(arg1 + this.name + arg2);
        }
        var mike = new Human("Mike");

        // call: greetのthisをmikeにして実行
        greet.call(mike, "Hello ","!!");
        // apply: callの引数がarray版
        greet.apply(mike, ["Hello ","!!"]);
        // bind: thisをmikeにして新しい関数を定義してそれを実行
        var greetMorning = greet.bind(mike);
        greetMorning("Good Morning ","!!");

イベント

基本的なイベントリスナーの書き方

var e = document.getElementById("foo");
    function callback(){
        alert("maroni");
    }
    e.addEventListener("click", callback, false);

イベントオブジェクト

イベントの情報を格納。イベントが最初に起きた時点で生成される。登録した関数は、イベントオブジェクトを第1引数として処理。

イベントオブジェクトが持つプロパティとメソッド

プロパティ名 内容
type イベントの名前
target イベント発生対象のDOM要素
currentTarget callback関数が発生しているDOM要素
<div id="foo"><div><div><div><div><div ><div><p>foo</p></div></div></div></div></div></div></div>
    
    <script>
   var e = document.getElementById("foo");
   function callback(e){
       alert(e.currentTarget); // このときdivを示す。 e.targetならpを示す。
   }
   e.addEventListener("click", callback, false);
   </script>

イベントフェーズ

イベントは3つのフェーズで構成される。

フェーズ名 フェーズ範囲
キャプチャフェーズ ドキュメントルートからイベントターゲットまで
ターゲットフェーズ イベントの発生箇所
パブリングフェーズ キャプチャフェーズの逆

ここがとても参考になった!

キャプチャリングとバブリングとpreventDefault()とstopPropagation() - 車輪を再発明 / koba04の日記

Canvas

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

ctx.beginPath(); // パスの初期化
// ctx.fillStyle = "#99ff66"
ctx.fillStyle = "rgba(255,0,0,0.5)"; // 色指定
// ctx.rect(0,0,100,200); // 長方形
ctx.arc(100,100,40,0,Math.PI*2) // 円

ctx.fill(); // 塗りつぶす
ctx.closePath(); //パスの終わり
メソッド 内容
moveTo(x,y) 引数で指定された位置にサブパスの始点を作成
lineTo(x,y) 直前の位置から、引数で指定された位置まで直線を引く
quadraticCurveTo(cpx,coy,x,y) 現在のパスに地点を加え、始点の制御点を伴う2次ベジェ曲線を使って直線の地点と接続する
bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y) 現在のパスに地点を加え、始点の制御点を伴う3次ベジェ曲線を使って直線の地点と接続する
arcTo() 現在のパスに1つ目の地点を追加。その地点は直線によって直前の地点に接続。現在のパスに2つ目の地点が追加。その地点はプロパティが引数で指定される円弧によって直前の地点に接続される

|メソッド名|内容| |--------|---------| |setTimeout(関数,ms)|指定ms後に関数を実行| |setinterval(関数,ms)|指定ms間隔で関数を実行.ブラウザ上でタブが非アクティブな状態になると処理が軽減される| うーん。慣れんなあ。