JavaScript--スイング関数

5109 ワード

本文の内容は「JavaScript忍者秘籍」から来ています.
関数記憶
下記のコードを利用して関数記憶機能を完成できます.
var store = {
    nextId: 1,
    cache: {},
    add: function(fn) {
        if (!fn.id) {
            fn.id = store.nextId++;
            return !!(store.cache[fn.id] = fn);
        }
    }
};
使用シーン:addEventListenerおよびattachEventの解凍過程において、バインディングされた関数はそのまま入ってくる必要があるので、バインディングされた関数を保存して、バインディングされた関数を使用することができる.
自己記憶関数
自己記憶関数とは、関数自身が先に計算した結果を記憶することで、同じ計算を2回行うことを避け、性能を著しく向上させることができるということです.例えば、この検出は素数の関数ですか?
    function isPrime(value) {
        if (!isPrime.results) {
            isPrime.results = {};
        }
        if (isPrime.results[value] !== undefined) {
            return isPrime.results[value];
        }
        var prime = value !== 1;
        for(var i = 2; i < value; i++) {
            if (value % i === 0) {
                prime = false;
                break;
            }
        }
        return isPrime.results[value] = prime;
    }
キャッシュメモリには2つの利点があります.
  • は、関数が取得を呼び出す前に結果を計算すると、最終的にユーザがパフォーマンスの利点を有する.
  • は舞台裏で発生して、完全にシームレスで、最終ユーザーとページ開発者はすべて特殊な操作がいらないで、あるいはこのためにいかなる追加の初期化の仕事をします.
  • DOMの取得動作にキャッシュメモリを使用すると、以下のように5倍の性能向上が得られます.
    function getElements(name) {
        if (!getElements.cache) {
            getElements.cache = {};
        }
    
        return getElements.cache[name] = 
            getElements.cache[name] ||
            document.getElementsByTagName(name); 
    }
    
    上記の素数を求める例では、実際には関数で結果をキャッシュしていますが、このような実現は私たちが関数体を取得できる時にのみ使用できます.上の関数を書き換えます.
    Function.prototype.memoized = function(key) {
        this._values = this._values || {};
    
        return this._values[key] !== undefined ?
            this._values[key] :
            this._values[key] = this.call(this, key);
    };
    
    function isPrime(num) {
        var prime = num != 1;
    
        for(var i = 2; i < num; i++) {
            if (num % i === 0) {
                prime = false;
                break;
            }
        }
    
        return prime;
    }
    
    console.log(isPrime.memoized(5));
    console.log(isPrime._values[5]);
    
    このような書き方は、先ほど私たちが提案した関数を取得できない問題を解決できますが、上の関数は、isPrime()を使用する時に、.memoized()に従わなければならないという問題がありました.
    Function.prototype.memoized = function(key) {
        this._values = this._values || {};
    
        return this._values[key] !== undefined ?
            this._values[key] :
            this._values[key] = this.call(this, key);
    };
    
    Function.prototype.memoize = function(key) {
        var fn = this;
        return function() {
            return fn.memoized.call(fn, key);
        }
    };
    
    var isPrime = (function(num) {
        var prime = num !== 1;
    
        for(var i = 2; i < num; i++) {
            if (num % i === 0) {
                prime = false;
                break;
            }
        }
    
        return prime;
    }).memoize();
    
    console.log(isPrime(5));
    
    しかし、上記の機能は全部Functionに追加されており、すべての関数のインスタンスによって共有されています.もしこのようにすることに違和感があるなら、次のような方法が使えます.
    function memoize(fn) {
        var cache = {};
    
        return function(key) {
            console.log("before: " + cache[key]);
            return cache[key] !== undefined ?
                cache[key] :
                cache[key] = fn.call(this, key);
        }
    }
    
    キャッシュする関数だけを包装すればいいです.
    関数判定
    一般的には、関数タイプを判断するには、typeof functionNameを利用するだけでよい(文字列functionを返すことができる).でも、いくつかの特殊な状況があります.例えば、以下のような判断を無効にします.
  • Opera:HTML typeofでは、 たちが むfunctionではなくobjectを します.(Firefoxにこの があると に いていますが、 で べてみたら、 のパソコンのFirefoxには の がなかったです. にOperaにはこの がありました.)
  • Safari:SafariDOMNodeListが つのfunctionであると えているので、typeof document.body.childNodes == function.( でやってみませんでした)
  • の に づいて、 な を さなければなりませんが、 には な は しません.コードは の りです
    function isFunction(fn) {
        return Object.prototype.toString.call(fn) === "[object Function]";  
    }
    
    この を して、Object.toString()などの のオブジェクトを することもできる.
    ここで String, RegExp, Dateを び さない は つあります.
  • なるオブジェクトは、 のfn.toString() で されるかもしれない.
  • toString()のうちのほとんどのタイプは、JavaScriptが するtoString()の をカバーするために め されたObject.prototype を っている.
  • toString()およびStringArrayに き えられたObjectの が から かる.
    var sContent = "Hello World";
    console.log(sContent.toString());   // "Hello World"
    
    var aContent = [1, 2, 3];
    console.log(aContent.toString());   // "[1, 2, 3]" 
    
    ほど べたように、この の は に いだけであり、toString()においてIE の がDOMに されるようなエラーがあることを している.

    ある ( も かりません)で、 を に することができます. な は の りです.
    var eles = {
        length: 0,
        add: function(ele) {
            Array.prototype.push.call(this, ele);
        }
    };
    
    objectオブジェクトにeles が され、length が されると、push は に する.