国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JS專題之memoization

zhisheng / 866人閱讀

摘要:前言在計(jì)算機(jī)領(lǐng)域,記憶是主要用于加速程序計(jì)算的一種優(yōu)化技術(shù),它使得函數(shù)避免重復(fù)演算之前已被處理過的輸入,而返回已緩存的結(jié)果。被執(zhí)行了不是素?cái)?shù),其他數(shù)字默認(rèn)是素?cái)?shù)。我們可以看出,如果從開始打印斐波那契數(shù)列,函數(shù)被執(zhí)行了次。

前言
在計(jì)算機(jī)領(lǐng)域,記憶(memoization)是主要用于加速程序計(jì)算的一種優(yōu)化技術(shù),它使得函數(shù)避免重復(fù)演算之前已被處理過的輸入,而返回已緩存的結(jié)果。  -- wikipedia

Memoization 的原理就是把函數(shù)的每次執(zhí)行結(jié)果都放入一個對象中,在接下來的執(zhí)行中,在對象中查找是否已經(jīng)有相應(yīng)執(zhí)行過的值,如果有,直接返回該值,沒有才真正執(zhí)行函數(shù)體的求值部分。在對象里找值是要比執(zhí)行函數(shù)的速度要快的。

另外,Memoization 只適用于確定性算法,對于相同的輸入總是生成相同的輸出,即純函數(shù)。

一、簡單實(shí)現(xiàn)

通過 Memoization 的定義和原理,我們就可以初步實(shí)現(xiàn) Memoization 了。

let memoize = function(func) {
  let cache = {};
  return function(key) {
    if (!cache[key])
      cache[key] = func.apply(this, arguments);
    return cache[key];
  }
}

是不是很簡單~ 函數(shù)記憶其實(shí)就是利用閉包,將函數(shù)參數(shù)作為存儲對象的鍵(key),函數(shù)結(jié)果作為存儲對象的 value 值。

二、underscore 實(shí)現(xiàn)

underscore 的源碼中有 Memoization 方法的封裝,它支持傳入一個 hasher 用來計(jì)算緩存對象 key 的計(jì)算方式。

_.memoize = function(func, hasher) {
  var memoize = function(key) {
    // 把存儲對象的引用拿出來,便于后面代碼使用
    var cache = memoize.cache;

    // hasher 是計(jì)算 key 值的方法函數(shù)。
    // 如果傳入了 hasher,則用 hasher 函數(shù)來計(jì)算 key
    // 否則用 參數(shù) key(即 memoize 方法傳入的第一個參數(shù))當(dāng) key
    var address = "" + (hasher ? hasher.apply(this, arguments) : key);

    // 如果 key 還沒有對應(yīng)的 hash 值(意味著沒有緩存值,沒有計(jì)算過該輸入)
    // 就執(zhí)行回調(diào)函數(shù),并緩存結(jié)果值
    if (!_.has(cache, address))
      cache[address] = func.apply(this, arguments);

    // 從緩存對象中取結(jié)果值
    return cache[address];
  };

  // cache 對象被當(dāng)做 key-value 鍵值對緩存中間運(yùn)算結(jié)果
  memoize.cache = {};

  // 返回 momoize 函數(shù), 由于返回函數(shù)內(nèi)部引用了 memoize.cache, 構(gòu)成了閉包,變量保存在了內(nèi)存中。
  return memoize;
};
三、應(yīng)用 - 判斷素?cái)?shù)
質(zhì)數(shù)為在大于 1 的自然數(shù)中,除了 1 和它本身以外不再有其他因數(shù)。

我們通過判斷素?cái)?shù)的函數(shù),看看使用了函數(shù)記憶后的效果。

function isPrime(value) {
  console.log("isPrime 被執(zhí)行了!");
  var prime = value != 1; // 1 不是素?cái)?shù),其他數(shù)字默認(rèn)是素?cái)?shù)。
  for (var i = 2; i < value; i++) {
    if (value % i == 0) {
      prime = false;
      break;
    }
  }
  return prime
}

let momoizedIsPrime = memoize(isPrime);

momoizedIsPrime(5) // isPrime 被執(zhí)行了!
momoizedIsPrime(5) // 第二次執(zhí)行,沒有打印日志!
四、應(yīng)用 - 計(jì)算斐波那契數(shù)列
斐波那契數(shù)列的特點(diǎn)是后一個數(shù)等于前面兩個數(shù)的和

指的是這樣一個數(shù)列:1、1、2、3、5、8、13、21、……在數(shù)學(xué)上,斐波那契數(shù)列以如下被以遞歸的方法定義:F0=0,F(xiàn)1=1,F(xiàn)n=Fn-1+Fn-2

計(jì)算斐波那契數(shù)列是用來演示函數(shù)記憶很好的例子,因?yàn)橛?jì)算斐波那契數(shù)列函數(shù)里面用了大量的遞歸。

var count = 0;
var fibonacci = function(n) {
  count++;
  return n < 2 ? n : fibonacci(n - 2) + fibonacci(n - 1);
}

for(var i = 0; i<= 10; i++) {
    console.log(`i: ${i}, ` + fibonacci(i));
}

// i: 0, 0
// i: 1, 1
// i: 2, 1
// i: 3, 2
// i: 4, 3
// i: 5, 5
// i: 6, 8
// i: 7, 13
// i: 8, 21
// i: 9, 34
// i: 10, 55

console.log(count);  // 453 !!!

我們可以看出,如果從 0 開始打印斐波那契數(shù)列,fibonacci 函數(shù)被執(zhí)行了 453 次。那我們就犧牲一小部分內(nèi)存,用來緩存每次計(jì)算的值。

fibonacci = memoize(fibonacci);

for(var i = 0; i<= 10; i++) {
    console.log(`i: ${i}, ` + fibonacci(i));
}
console.log(count); // 12

通過 memoize 函數(shù)記憶,使得函數(shù)執(zhí)行次數(shù)只需要 12 次,大大優(yōu)化了函數(shù)執(zhí)行計(jì)算的性能消耗,

總結(jié)

函數(shù)記憶(memoization)將函數(shù)的參數(shù)和結(jié)果值,保存在對象當(dāng)中,用一部分的內(nèi)存開銷來提高程序計(jì)算的性能,常用在遞歸和重復(fù)運(yùn)算較多的場景。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/101566.html

相關(guān)文章

  • JavaScript專題函數(shù)記憶

    摘要:專題系列第十七篇,講解函數(shù)記憶與菲波那切數(shù)列的實(shí)現(xiàn)定義函數(shù)記憶是指將上次的計(jì)算結(jié)果緩存起來,當(dāng)下次調(diào)用時,如果遇到相同的參數(shù),就直接返回緩存中的數(shù)據(jù)。 JavaScript 專題系列第十七篇,講解函數(shù)記憶與菲波那切數(shù)列的實(shí)現(xiàn) 定義 函數(shù)記憶是指將上次的計(jì)算結(jié)果緩存起來,當(dāng)下次調(diào)用時,如果遇到相同的參數(shù),就直接返回緩存中的數(shù)據(jù)。 舉個例子: function add(a, b) { ...

    RobinTang 評論0 收藏0
  • JS專題垃圾回收

    摘要:如果沒有引用指向該對象零引用,對象將被垃圾回收機(jī)制回收。經(jīng)過增量標(biāo)記改進(jìn)后,垃圾回收的最大停頓時間可以減少到原來的左右。解除引用的真正作用是讓值脫離執(zhí)行環(huán)境,以便垃圾收集器下次運(yùn)行時將其回收。 前言 在講 JS 的垃圾回收(Garbage Collection)之前,我們回顧上一篇《JS專題之memoization》,memoization 的原理是以參數(shù)作為 key,函數(shù)結(jié)果作為 v...

    liujs 評論0 收藏0
  • Memoization in JavaScript

    摘要:源碼函數(shù)調(diào)用過,沒有變化,參數(shù)時返回緩存值。而通過,可以把上一次的計(jì)算結(jié)果保存下來,而避免重復(fù)計(jì)算。這意味著將跳過渲染組件,并重用最后渲染的結(jié)果。 1. 基本概念 在一個CPU密集型應(yīng)用中,我們可以使用Memoization來進(jìn)行優(yōu)化,其主要用于通過存儲昂貴的函數(shù)調(diào)用的結(jié)果來加速程序,并在再次發(fā)生相同的輸入時返回緩存的結(jié)果。例如一個簡單的求平方根的函數(shù): const sqrt = Ma...

    ccj659 評論0 收藏0
  • JS專題數(shù)組去重

    摘要:將元素作為對象的鍵,默認(rèn)鍵對應(yīng)的值為如果對象中沒有這個鍵,則將這個元素放入結(jié)果數(shù)組中去。 前言 數(shù)組去重在日常開發(fā)中的使用頻率還是較高的,也是網(wǎng)上隨便一抓一大把的話題,所以,我寫這篇文章目的在于歸納和總結(jié),既然很多人都在提的數(shù)組去重,自己到底了解多少呢。又或者是如果自己在開發(fā)中遇到了去重的需求,自己能想到更好的解決方案嗎。 這次我們來理一理怎么做數(shù)組去重才能做得最合適,既要考慮兼容性,...

    only_do 評論0 收藏0
  • 【譯】你可能不需要派生狀態(tài)

    摘要:所有派生狀態(tài)導(dǎo)致的問題無異于兩種無條件的根據(jù)來更新無論和是否匹配來更新。派生狀態(tài)最常見的錯誤就是將這兩者混和在一起。因此通常被用于性能優(yōu)化而不是來判斷派生狀態(tài)的正確性。我們可以使用派生狀態(tài)來存儲過濾列表這種方式避免了重新計(jì)算。 原文鏈接:https://reactjs.org/blog/2018... 翻譯這篇文章的起因是因?yàn)樵谝淮涡枨蟮绣e誤的使用了getDerivedState...

    dinfer 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<