JavaScript 设计模式与开发实践读书笔记

JavaScript 设计模式与开发实践读书笔记

最近利用碎片时间在 Kindle 上面阅读《JavaScript 设计模式与开发实践读书》这本书,刚开始阅读前两章内容,和大家分享下我觉得可以在项目中用的上的一些笔记。

我的 github 项目会不定时更新,有需要的同学可以移步到我的 github 中去查看源码:https://github.com/lichenbuliren/design-mode-notes

1、currying 函数柯里化

currying 又称部分求值。一个 currying 的函数首先会接受一些参数,接受了这些参数之后,该函数并不会立即求值,而是继续返回另外一个函数,将刚才传入的参数在函数形成的闭包中被保存起来。待到函数被真正需要求值的时候,之前传入的所有参数都会被一次性的用于求值。

假设我们需要编写一个计算每个月开销的函数,在每天结束之前,我们要记录每天花掉了多少钱。

通用 currying 函数:

var currying = function(fn) {
var args = [];

return function() {
if (arguments.length === 0) {
return fn.apply(this, args);
} else {
[].push.apply(args, arguments);
// 返回函数本身,这里指向 return 后面的匿名函数!
return arguments.callee;
}
}
};

var cost = (function() {
// 闭包存储最后的值
var money = 0;

return function() {
for (var i = 0, len = arguments.length; i

2、uncurrying 函数

Function.prototype.uncurrying = function() {
// 此时 selft 是后面例子中的 Array.prototype.push;
var self = this;

return function() {
// arguments: { '0': { '0': 1, length: 1 }, '1': 2 }
var obj = Array.prototype.shift.call(arguments);
return self.apply(obj, arguments);
}
};

// 另外一种实现方式
Function.prototype.uncurrying = function() {
var self = this;

return function() {
return Function.prototype.call.apply(self, arguments);
}
};

var push = Array.prototype.push.uncurrying();

var obj = {
"length": 1,
"0": 1
};

push(obj, 2);
console.log(obj);

3、函数节流

JavaScript 中的函数大多数情况下都是由用户主动调用触发的,除非是函数本身的实现不合理,否则我们一般不会遇到跟性能相关的问题。但是在一些少数情况下,函数的触发不是有由用户直接控制的。在这些场景下,函数有可能被非常频繁的调用,而造成大的性能问题。

函数被频繁调用的场景:

  1. window.onresize 事件

  2. mousemove 事件

  3. 上传进度

函数节流原理

上面三个提到的场景,可以发现它们面临的共同问题是函数被触发的频率太高。

比如我们在 window.onresize 事件中要打印当前浏览器窗口大小,在我们拖拽改变窗口大小的时候,控制台1秒钟进行了 10 次。而我们实际上只需要 2 次或者 3 次。这就需要我们按时间段来忽略掉一些事件请求,比如确保在 500ms 内打印一次。很显然,我们可以借助 setTimeout 来完成。

函数节流实现

/

  • 函数节流实现
  • @param {Function} fn 需要节流执行的函数
  • @param {[type]} interval 事件执行间隔时间,单位 ms
  • @return {[type]} [description]
    */
    var throttle = function(fn, interval) {
    var _self = fn,
    timer,
    firstTime = true;

console.log(_self);

return function() {
var args = arguments,
_me = this; // 这里代表当前的匿名函数

console.log(_me);if (firstTime) {  _self.apply(_me, args);  return firstTime = false;}if (timer) {  return false;}timer = setTimeout(function() {  clearTimeout(timer);  timer = null;  _self.apply(_me, args);}, interval || 500);

};
};

window.onresize = throttle(function() {
console.log('test');
}, 500);

4、分时函数

我们经常会遇到这么一种情况,某些函数确实是用户主动调用的,但是因为一些客观原因,这些函数会严重地影响页面性能。

一个例子就是创建 WebQQ 的 QQ 好友列表。列表中通常会有成百上千个好友,如果一个好友用一个节点来表示,当我们在页面中渲染这个列表的时候,可能要一次性往页面中创建成百上千个节点。

在短时间内往页面中大量添加 DOM 节点显然也会让浏览器吃不消,我们看到的结果往往就是浏览器的卡顿甚至假死。所以我们需要一个分时函数来解决这个问题

/

  • 分时函数例子
  • 以创建 WebQQ 列表为例
  • @param {[type]} data 函数执行需要用到的数据
  • @param {Function} fn 真正需要分时执行的函数
  • @param {[type]} count 每次创建一批节点的数量
  • @param {[type]} interval 函数执行间隔
  • @return {[type]} [description]
    */
    var timeChunk = function(data, fn, count, interval) {
    var t;

var len = data.length;

var start = function() {
for (var i = 0; i

5、惰性加载函数

以创建事件绑定函数为例:
在进入第一个条件分支之后,在函数内部重写这个函数,重写之后,就是我们所需要的函数,在下一次进入的时候,就不再需要判断了。

/

  • 事件绑定
  • @param {[type]} el [description]
  • @param {[type]} type [description]
  • @param {[type]} handler [description]
    */
    var addEvent = function(el, type, handler) {
    if (window.addEventListener) {
    addEvent = function(el, type, handler) {
    el.addEventListener(type, handler, false);
    }
    } else if (window.attachEvent) {
    addEvent = function(el, type, handler) {
    el.attachEvent('on' + type, handler);
    }
    }

addEvent(el, type, handler);
}

Q&A

暂时这么多,以后会不定期更新一些关于我读这本书的笔记内容!

关键字:JavaScript, 设计模式, 笔记

版权声明

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部