我是靠谱客的博主 淡淡哈密瓜,最近开发中收集的这篇文章主要介绍(JavaScript)装饰器模式和转发(透明缓存、“func.call”函数、如何传递多个参数、func.apply),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

透明缓存

利用装饰者模式给一个函数添加缓存

function slow(x) {
// 这里可能会有重负载的 CPU 密集型工作
alert(`Called with ${x}`);
return x;
}
//缓存装饰器:将函数func运算结果添加到缓存中
function cachingDecorator(func) {
let cache = new Map();
return function(x) {
if (cache.has(x)) {
return cache.get(x);
}
let result = func(x);
cache.set(x, result);
return result;
};
}
slow = cachingDecorator(slow);
//1不会和装饰器中的形参匹配,直接保存在arguments中,和java有区别
alert( slow(1) ); // slow(1) 被缓存下来了
alert( "Again: " + slow(1) ); // 一样的
alert( slow(2) ); // slow(2) 被缓存下来了
alert( "Again: " + slow(2) ); // 和前面一行结果相同

“func.call”函数

// 我们将对 worker.slow 的结果进行缓存
let worker = {
someMethod() {
return 1;
},
slow(x) {
return x * this.someMethod();
}
};
// 缓存装饰器
function cachingDecorator(func) {
let cache = new Map();
return function(x) {
if (cache.has(x)) {
return cache.get(x);
}
let result = func(x);
cache.set(x, result);
return result;
};
}
alert( worker.slow(1) ); // 原始方法有效
worker.slow = cachingDecorator(worker.slow); // 现在对其进行缓存
alert( worker.slow(2) ); // Error: Cannot read property 'someMethod' of undefined

和下面代码情况类似:

let func = worker.slow;
func(2);

包装器将调用传递给原始方法,但没有上下文 this。因此,发生了错误。


解决方案:
//第一个参数作为this,后面的作为参数,func是需要调用call()方法的函数
func.call(context, arg1, arg2, ...)
代码:
let worker = {
someMethod() {
return 1;
},
slow(x) {
return x * this.someMethod();
}
};
function cachingDecorator(func) {
let cache = new Map();
return function(x) {
if (cache.has(x)) {
return cache.get(x);
}
let result = func.call(this, x); // 现在 "this" 被正确地传递了
cache.set(x, result);
return result;
};
}
worker.slow = cachingDecorator(worker.slow);
alert( worker.slow(2) ); // 工作正常
alert( worker.slow(2) ); // 工作正常,没有调用原始函数(使用的缓存)

如何传递多个参数:

map储存只能以key,value一对一形式储存,也就是一个参数对应一个结果,如何储存多个参数呢?

解决方案:

1.实现一个新的(或使用第三方的)类似 map 的更通用并且允许多个键的数据结构。
2.使用嵌套 map:cache.set(min) 将是一个存储(键值)对 (max, result) 的 Map。所以我们可以使用 cache.get(min).get(max) 来获取 result。
3.将参数转化为字符串

第三种方式代码:
let worker = {
slow(min, max) {
return min + max;
}
};
function cachingDecorator(func, hash) {
let cache = new Map();
return function() {
let key = hash(arguments); //hash函数用来将参数转化为字符串
if (cache.has(key)) {
return cache.get(key);
}
let result = func.call(this, ...arguments); // (**)
cache.set(key, result);
return result;
};
}
function hash(args) {
return args[0] + ',' + args[1];
}
worker.slow = cachingDecorator(worker.slow, hash);
alert( worker.slow(3, 5) );
alert( "Again " + worker.slow(3, 5) ); // same (cached)

func.apply

func.apply(context, args)

call 和 apply 之间唯一的语法区别是,call 期望一个参数列表,而 apply 期望一个包含这些参数的类数组对象。

因此,这两个调用几乎是等效的:


对hash函数进行改进

function hash(args) {
return args.join();
}

这种方法不可以,因为arguments 对象既是可迭代对象又是类数组对象,但它并不是真正的数组。

function hash() {
alert( [].join.call(arguments) ); // 1,2
}
hash(1, 2);

这个技巧称为方法借用
我们从常规数组 [].join 中获取(借用)join 方法,并使用 [].join.call 在 arguments 的上下文中运行它。

最后

以上就是淡淡哈密瓜为你收集整理的(JavaScript)装饰器模式和转发(透明缓存、“func.call”函数、如何传递多个参数、func.apply)的全部内容,希望文章能够帮你解决(JavaScript)装饰器模式和转发(透明缓存、“func.call”函数、如何传递多个参数、func.apply)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(71)

评论列表共有 0 条评论

立即
投稿
返回
顶部