浅谈js自记忆函数,挥舞函数

时间:2020-02-08 00:39来源:亚洲城ca88唯一官方网站
经过那句话能够得出,自记念函数实际就是能力所能达到记住上次计算结果的函数。在完成中,大家可以那样实行管理:当函数计算获得结果时,就将该结果根据参数存款和储蓄起来。

经过那句话能够得出,自记念函数实际就是能力所能达到记住上次计算结果的函数。在完成中,大家可以那样实行管理:当函数计算获得结果时,就将该结果根据参数存款和储蓄起来。采纳这种措施时,假诺其余二个调用也运用同样的参数,大家则能够一直回到上次囤积的结果并不是再总括叁遍。

本文中的内容出自于 《JavaScript 忍者秘籍》。

时间: 2018-07-26阅读: 839标签: js知识

函数存款和储蓄

采纳以下代码能够达成函数存款和储蓄功用。

var store = {
    nextId: 1,
    cache: {},
    add: function(fn) {
        if (!fn.id) {
            fn.id = store.nextId  ;
            return !!(store.cache[fn.id] = fn);
        }
    }
};

选取处境:能够用来囤积事件的回调函数,由于在 addEventListenerattachEvent 的解绑进程中都亟待原样传入绑定的函数,所以我们能够将绑定的函数存款和储蓄下来,以供解绑事件时选取。

最近阅读《JavaScript忍者秘技》看见了意气风发种有意思的函数:自记念函数。

杜撰数组

出于某种指标(笔者也不明了),大家得以将对象伪变成贰个数组,具体操作如下:

var eles = {
    length: 0,
    add: function(ele) {
        Array.prototype.push.call(this, ele);
    }
};

eles 对象加多了五个 length 属性,当调用 push 方法时,length 属性会自动扩展。

风度翩翩旦参数是一个全新的值,进行常规的素数检查实验。

函数剖断

相通来说,要一口咬住不放三个函数类型,只必要利用 typeof functionName 就能够(会回到字符串 function)。然则会有少年老成对破例景况让我们的判别失效,比如上面三种:

  1. Opera: 在 HTML<object> 成分上使用 typeof的话,会返回 function,并非大家希望的 object。(书中说在 Firefox 中会现身这么些难题,可是小编切身检查测验之后,发掘本身计算机上的 Firefox并未现身上述难题,反而是 Opera 现身了这一个主题素材 )。

  2. Safari: Safari 认为 DOMNodeList 是一个 function,所以 typeof document.body.childNodes == function。(自甲午亲自品尝)

依附以上情状,大家必要寻觅生龙活虎种完美的解决方案,然而事实上并官样文章完美的减轻方案,倒是有黄金年代种恍若完美的方案,那正是利用 Object.toString() 方法。代码如下:

function isFunction(fn) {
    return Object.prototype.toString.call(fn) === "[object Function]";  
}

利用那项本领,还足以肯定 String, RegExp, Date等其余对象。

这里大家不直接调用 fn.toString() 的开始和结果有四个:

  1. 今是昨非的靶子或然有和好的 toString() 方法完成。

  2. JavaScript 中的大繁多连串都原来就有多个预订义的 toString() 方法覆盖了 Object.prototype 提供的 toString() 方法。

从上面能够看看 StringArray 重写了 ObjecttoString() 方法。

var sContent = "Hello World";
console.log(sContent.toString());   // "Hello World"

var aContent = [1, 2, 3];
console.log(aContent.toString());   // "[1, 2, 3]" 

刚才早已聊起,上面这么些检查测试的艺术只是近乎完美,那表达它也会有出错的动静,比方在 IE 中会将 DOM 成分的法子告诉成 object

只是,自纪念函数并非完美的,它后生可畏律享有缺陷:

自回忆函数

所谓自纪念函数,正是说函数本身能够记住先前测算的结果,那样就能够幸免同生机勃勃的计量实施两回,能够如数家珍的增长品质。举例说下边那几个检查测验是还是不是为素数的函数。

    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;
    }

缓存回想有五个优点:

  1. 在函数调用获取早先计算结果的时候,最终客户享有质量优势。
  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);
    }
}

只要求对要缓存的函数举办打包就能够。

终极,存储并赶回计算值。


来源:

简介

首先,检查它的answers属性来认可是不是曾经有自回想的缓存,若无,制造二个。

多少个自记念函数的事例

家喻户晓,像这样幸免既重复又繁杂的猜度能够明显狠抓品质。对于动漫中的总计、找出不日常转移的多少或别的耗费时间的数学总计来讲,回忆化这种方法是特别立见成效的。

isPrime函数是七个自回想素数检验函数,每当它被调用时:

由于函数调用时会寻觅早前调用所收获的值,所以客户最终会愿意见到所拿到的性质收益。它没有要求实行其余异样要求,也不供给做任何额外开始化,就会顺遂进行专门的学业。

何为自回想函数?书中涉及:

总结

其余类型的缓存都自然会为质量就义内部存款和储蓄器。很四个人以为缓存逻辑不应有和业务逻辑混合,函数或情势只必要把大器晚成件专门的学业办好。对自纪念函数很难做负载测量检验或估量算法复杂度,因为结果信任于函数在此以前的输入。

上面这一个例子表现自纪念函数的劳作方法:

自记念函数有八个优点:

回想化(memoization)是黄金年代种营造函数的管理进程,能够记住上次总结结果

接下去,检查参数在此之前是否已经被缓存过,假若在缓存中找到该值,直接回到缓存的结果。

// 自记忆素数检测函数function isPrime (value) { // 创建缓存 if (!isPrime.answers) { isPrime.answers = {}; } // 检查缓存的值 if (isPrime.answers[value] !== undefined) { return isPrime.answers[value]; } // 0和1不是素数 var prime = value !== 0  value !== 1; // 检查是否为素数 for (var i = 2; i  value; i  ) { if (value % i === 0) { prime = false; break; } } // 存储计算值 return isPrime.answers[value] = prime}

编辑:亚洲城ca88唯一官方网站 本文来源:浅谈js自记忆函数,挥舞函数

关键词: 亚洲城ca88