Comments (22)
补充几个适用场景,其实作者在多说一句中已经讲出了精髓,需要大量重复的计算,或者大量计算又依赖于之前的结果
最大公约数(GCD)
function gcd(a,b){
var temp;
if (a < b) temp=b, b=a, a=temp; // if a < b,switch
while(b != 0) temp=b, b = a%b, a=temp;
return a;
}
阶乘(factorial)
function factorial(n) {
return (n <= 1) ? 1 : n * factorial(n-1);
}
可能都是些偏向数学的解决。但是扩展了思路,在遇到动态规划的问题时,更难想到优化点,比如很典型的上楼梯一次可以一步或者两部,问上10级有多少种走法,其实就有那么一些fibonacci的味道在里面。
更值得一提的是,memoize并不是拼错了也不是直觉中的memorize,memo是备忘录的意思,比如大家记下自己遇到的bug,以备在今后遇到时能尽快查找,和memory的记忆的概念是不同的,而动态规划中比较常见的有个备忘录算法,和这里的memo有相似之处(个人之见)。
(另,我一直好奇表情是怎么发的哈哈哈哈
from blog.
第一版中,
function memoize(f) {}
var memoizedAdd = memorize(add)
这里名字不一致,笔误了
from blog.
判断 typeof cache[address] === 'undefined'
可以避开结果为 0 时又重新计算一次的问题
当然也要根据返回值的类型来确认缓存判空的方式,以上只是针对返回值类型为 number
时的情况
from blog.
第二版描述,"就会自动调用 toString 方法转换成 [Object object]",应该是 [object Object]吧
from blog.
第一版里用到了【语句的结果值】,看起来感觉不太好...
// 第一版 (来自《JavaScript权威指南》)
function memoize(f) {
var cache = {};
return function(){
...
else return cache[key] = f.apply(this, arguments) // 赋值表达式的值
}
}
from blog.
@BuptStEve 哈哈,那我修改一下~
from blog.
@HowardTangHw 非常感谢指出哈,请一定要接受我迟到的感谢~
from blog.
您好,请问这个var key = arguments.length + Array.prototype.join.call(arguments, ",");
里的length是啥意思为啥要加到开头?
我console.log之后是
{ '0': 1, '1': 2, '2': 3 }
31,2,3
这样?
原谅我比较笨o(TωT)o ....
from blog.
@vanishcode 应该是担心 Array.prototype.join.call(arguments, ",") 会导致缓存的 key 值相同,比如在一些特殊情况下:
function add(a, b) {
console.log(a + b);
}
var memoizedAdd = memoize(add);
memoizedAdd(1, 2); // 3
memoizedAdd('1,2') // 3
from blog.
单词拼写少了一个字母
memorize 少了r
from blog.
@zhangruinian 其实没有拼写错误,underscore 和 lodash 都是用的 memoize,memoization来源于memo,备忘录的意思,因为这个方法主要是记录一个值,以便以后可以搜索它。
from blog.
为什么所有文章都没有【参考资料】一节
from blog.
其实就是设计模式里的工厂模式, 判断创建的对象是否存在于存列表
from blog.
方案一不使用 [].join
而是 JSON.stringify(arguments)
就能解决入参是对象的问题了吧
from blog.
个人认为这个函数记忆就是设计模式中的代理模式,在函数中增加了缓存代理。
如果项目中有图表需要展示历史数据时,这会是一个很好的使用场景。正常的写法就是选择一个日期,然后发送一个http请求。但是在历史数据这种场景中,其实没必要去不停的请求服务器。下面是我写的一个简单的例子,大家可以看看。如有不对,务必指出。谢谢!
const getData = (() => {
// 缓存
const cache = new Map();
return async function(date) {
if (cache.has(date)) {
return new Pormise((resolve) => {
resolve(cache.get(date))
})
}
return request('POST', '/list/history', { date })
.then(data => {
// 设置缓存
cache.set(date, data);
return data;
})
}
})()
const data = await getData('2019-12-31');
from blog.
大佬你好,前端小菜鸡想问下为啥第二版内部的memoize函数里参数key就是add函数的第一个参数呢
from blog.
其实就是设计模式里的工厂模式, 判断创建的对象是否存在于存列表
这里与工厂模式还不一样 工厂模式主要处理类 也就是处理多个类(简单工厂)或者多个工厂(复杂工厂)的过程
这里更像是代理模式 函数记忆也就是代理模式中的缓存代理
from blog.
大佬你好,前端小菜鸡想问下为啥第二版内部的memoize函数里参数key就是add函数的第一个参数呢
你好 因为我们平时写的function fn(a,b,c){...}
中a
是第一个参数,自然function fn(key){...}
中key
是第一个参数啦
from blog.
前面的专题还能吸收点,后面看着太跳级了,还是买两本书啃完再来了。
from blog.
@vanishcode 应该是担心 Array.prototype.join.call(arguments, ",") 会导致缓存的 key 值相同,比如在一些特殊情况下:
function add(a, b) { console.log(a + b); } var memoizedAdd = memoize(add); memoizedAdd(1, 2); // 3 memoizedAdd('1,2') // 3
看这一段的时候没有想到~~哈哈哈哈哈,本以为去掉前面的length拼接问题也不大。。。。。学习到了
from blog.
大佬你好,前端小菜鸡想问下为啥第二版内部的memoize函数里参数key就是add函数的第一个参数呢
var memoizedAdd = memoize(add)
这一句其实就是返回memoize的函数重写,即:
var memoize = function(key) {
var cache = memoize.cache;
var address = '' + (hasher ? hasher.apply(this, arguments) : key);
if (!cache[address]) {
cache[address] = func.apply(this, arguments);
}
return cache[address];
};
所以在调用memoizedAdd(1,2,3)的时候key值就为1.
from blog.
使用ts改写了一下
- 这里默认是用fn作为,当然hasher就可以写为可选的类型
const memoize = function (fn: Function, hasher?: Function) {
let cache: any ={}
const menoize = function (...args: any[]) {
const address = "" + (hasher ? hasher.apply(null, args) : args)
if (!cache[address]) {
cache[address] = fn.apply(null, args)
}
return cache[address]
}
return menoize
}
let add = function (a: number, b: number, c: number) {
return a + b + c
}
let memoizedAdd = memoize(add)
console.log(memoizedAdd(1, 2, 3))
from blog.
Related Issues (20)
- 大佬您好,看完大有收获,但是遇到了个问题,不太会解释它的执行上下文入栈出栈顺序,关于尾递归,顺序是怎样呢? HOT 1
- 冴羽答读者问:如何在工作中打造影响力,带动同事?
- 无
- 冴羽答读者问:如何学习更有计划性、提升更稳更快? HOT 4
- 冴羽答读者问:过程比结果重要吗? HOT 1
- 冴羽答读者问:冴羽,你为什么写起了鸡汤? HOT 3
- 聊聊 npm 的语义化版本(Semver) HOT 4
- How to create Backlinks 😤
- 思考题第2题
- 可以理解为原型是prototype,原型链是通过__proto__ 链接起来的吗
- React 之 createElement 源码解读 HOT 8
- React 之元素与组件的区别 HOT 1
- React 之 Refs 的使用和 forwardRef 的源码解读
- React 之 Context 的变迁与背后实现 HOT 1
- 第一段不报错啊,刚试过了,会打印1
- how can i HOT 1
- Hosting of Blog Issue
- 全局对象
- 为啥每次都要创建一个 Child函数来new 子类?现在不都是 const p1 = new Person(); const p2 = new Person()吗
- 文档内容中文件结构的错位 HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from blog.