理解JavaScript定时器:setTimeout和setInterval

定时器其实并不是JavaScript提供的,而是由浏览器(对于前端来说)提供的。所以setTimeout()setInterval()这两个方法均是通过浏览器的顶层对象window进行调用,可能平时大家在使用的过程中也会省去window而直接使用这两个方法。

这两个方法所接收的参数都一样:

1
2
setTimeout(func|code, delay);
setInterval(func|code, delay);

这两个方法总是被简单的认为:在多少毫秒之后就执行里面的函数或者每间隔多少毫秒就执行里面的函数,基于这种理解的话会遇到很多匪夷所思的坑。而结合上篇文章中所提到的执行队列来解释的话,很多疑问都可以迎刃而解。

前者:在指定的毫秒数后,将定时任务处理函数(func|code)添加到执行队列的队尾。

后者:按照指定的周期(以毫秒计),将定时任务处理函数(func|code)添加到执行队列的队尾。

阅读全文 »

JavaScript Event Loop 浅析

最近在学习Nodejs的过程中深入的了解了异步编程这个概念,为了更好的使用Nodejs,这些概念不可不知。在以前作为一个JavaScript用户的时候,完全是不知道它是怎么运行的,对好些概念也是“知其然不知其所以然”。

对于客户端的JavaScriptNodejs来说其实差距不是很大,这回就从客户端方面来说说Event Loop这个概念吧,算是异步编程的一个切入点吧。其实jQuery的作者John Resig在几年前就写了一篇好文章How JavaScript Timers Work,来讲述timer事件在浏览器中是怎样工作的,我也是通过这篇文章才“知其所以然”。

问题场景

先来看看一段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<a href="#" id="doBtn">do something</a>
<div id="status"></div>
<script type="text/javascript">
void function() {
var doBtn = document.getElementById('doBtn')
, status = document.getElementById('status');

doBtn.onclick = function(e) {
e.preventDefault();

status.innerText = 'doing...please wait...'; //开始啦
sleep(10000); //模拟一个耗时较长的计算过程,10s
status.innerText = 'done'; //完成啦
};
}();

function sleep(ms) {
var start = new Date();
while (new Date() - start <= ms) {}
}
</script>

上面代码主要想完成一个功能:按钮被点击时———>显示一个状态告知用户正在干一些事情———>开始干———>事情干完后状态变更为已完成。

阅读全文 »

像黑客一样写博客

“像黑客一样写博客”,这个标题是网络上对Octopress(其实应该是Jekyll)的评价,而这一评价是来自一篇几年前的文章。当我将自己的博客抹掉并重新开始的时候,我也准备以这个标题来作为这次的新起点。

其实早就有换掉WordPress的想法,一是因为它太臃肿了,我只是想简单的写写博客,用不着那么多强大的功能;二是它对插入代码的支持让我绝望了,每次用Markdown写好文章,复制其HTMLWordPress之后,都要调整好半天的样式;三是我之前的博客中太多的碎碎念之类的水文了,可谓杂、乱,并不像一个记录技术的博客。综合这些借口,我每次登录到WordPress后台都没有再写文章的激情。

阅读全文 »

JavaScript中创建类的方式

现在JavaScript这门技术已经到了一个引爆点,一年前我对它的了解都只停留在肤浅的网页客户端脚本语言,只会简单的玩玩jQueryExtJs,其实都算不上开发者,而是一个JavaScript用户。但今年的目标是做一个合格的前端攻城湿,所以恶补是必须的。

JavaScript中是其实不存在所谓“类”的概念,因为它并不是面向对象的语言。在面向对象中,一个最常见的说法就是:“类”是“对象”的模板,基本上都是采用语言内置的Classclass关键字来定义“类”。而JavaScript不存在这个概念,所以也没有提供类似的关键字(虽然classJavaScript的关键字,但是至今都没有实现,只是被保留而已)。

因此,在JavaScript中创建类就唯有使用模拟的方式,而模拟的手法多种多样,何时采用何种方式最合适,需视情况而定。以下就记录下常见的几种模式。

阅读全文 »

Backbone之旅:前端MVC架构初体验(下)

《Backbone之旅:前端MVC架构初体验(上)》,上篇中最后的代码已经完全达到最初提出的几点要求,现在就结合Backbone提供的能力,来继续精简代码。最后的目标就是将上篇中的代码全部重构为BackboneMVC模式。

上篇中最后一次改造就已经使用到了callback的方式,所以我们索性再加上Event机制吧,因为Backbone内置了这个能力。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
var events = _.clone(Backbone.Events);

var TodoList = function(){};

TodoList.prototype.add = function(options){
$.ajax({
url: '/add',
type: 'POST',
dataType: 'json',
data: { todoContent: options.todoContent },
success: options.success
});
};

var NewTodoView = function(options){
this.todoList = options.todoList;

events.on('todo:add', this.appendTodo, this);
events.on('todo:add', this.clearTextArea, this);

$('#new-todo form').submit($.proxy(this.addTodo, this));
};

NewTodoView.prototype.addTodo = function(e){
e.preventDefault();

this.todoList.add({
todoContent: $('#new-todo').find('textarea').val(),
success: function(data){
events.trigger('todo:add', data.todoContent);
}
});
};

/*后面不变*/

现在既然调用add()时传入的success属性已经完全不涉及到DOM操作了,而是单纯的事件触发,那完全可以把这个行为放置到TodoList原型的add()方法中去了,这样重用性更高。

阅读全文 »