Micro-Templating性能优化

2年前

这篇文章中,我简单介绍了前端模板引擎。John Resig写的tmpl函数麻雀虽小五脏俱全,足以满足日常开发需要。本文主要探讨一下tmpl的性能优化。

先复习一下tmpl的源代码:

var tmpl = (function() {
	var cache = { };

	return function(str, data) {
		var fn = cache[str];
		if (!fn) {
			fn = new Function("obj",
				"var p=[];" +
				"with(obj){p.push('" +
				str
					.replace(/[\r\t\n]/g, " ")
					.split("<%").join("\t")
					.replace(/((^|%>)[^\t]*)'/g, "$1\r")
					.replace(/\t=(.*?)%>/g, "',$1,'")
					.split("\t").join("');")
					.split("%>").join("p.push('")
					.split("\r").join("\\'")
				+ "');}return p.join('');"
			);
			cache[str] = fn;
		}

		return fn(data);
	};
})();
586次阅读,1条评论

ECMAScript 5中的属性描述符

2年前

属性描述符是ES5中新增的概念,其作用是给对象的属性增加更多的控制。

Object.defineProperty

要研究属性描述符,首先要谈谈 Object.defineProperty 方法。这个方法的作用是给对象定义新属性或修改已存在的属性。其原型如下:

Object.defineProperty(obj, prop, descriptor)

使用示例:

var obj = { };
Object.defineProperty(obj, 'attr', { value: 1 });
819次阅读,0条评论

从千分位格式化谈JS性能优化

3年前

所谓的数字千分位形式,即从个位数起,每三位之间加一个逗号。例如“10,000”。针对这个需求,我起初写了这样一个函数:

// 方法一
function toThousands(num) {
	var result = [ ], counter = 0;
	num = (num || 0).toString().split('');
	for (var i = num.length - 1; i >= 0; i--) {
		counter++;
		result.unshift(num[i]);
		if (!(counter % 3) && i != 0) { result.unshift(','); }
	}
	return result.join('');
}
2303次阅读,3条评论

动态创建iframe在IE下的两个问题

3年前

表单提交到动态创建的iframe

问题描述

以下代码,一般用于在当前页无刷新提交表单,其原理是把表单的target设为页面上某个iframe的id,使该iframe成为提交的目标,避免新开窗口或跳转。但这段代码在IE 6、7下无效。

<form action="http://www.baidu.com/" method="post" target="testframe">
	<input type="submit" value="Submit" />
</form>
<script>
var iframe = document.createElement('iframe');
iframe.id = 'testframe';
iframe.name = 'testframe';
document.body.insertBefore(iframe, document.body.firstChild);
</script>
1122次阅读,1条评论

通过WebRTC获取摄像头影像

3年前

WebRTCWeb Real-Time Communication,网页实时通信),是一个支持网页浏览器进行实时语音对话或视频对话的API,目前已经是W3C的推荐标准。本文主要阐述如何通过WebRTC的接口获取摄像头影像并截图。

获取摄像头影像

要播放摄像头的影像,首先需要一个video标签:

<video id="video"></video>

获取摄像头影像主要是通过navigator.getUserMedia这个接口,在caniuse.com上查询一下这个接口的支持情况,可以看到目前只有Chrome和Firefox支持得比较好,而且都要加上自家的前缀,移动端几乎全线不可用。

getUserMedia支持情况

5103次阅读,3条评论

通过开发者工具监控事件触发

4年前

我们经常会通过这样的代码去判断某个元素的某些事件有没有被触发:

$('body').on("click", function(e) {
	console.log(e);
});

事实上,Chrome开发者工具以及Firebug都提供了内置事件监控方法——monitorEvents。下面我们介绍一下具体用法。

审查一个元素,此时,你可以在控制台中通过变量$0获取这个元素:

$0变量

1061次阅读,2条评论

了解模块化开发

4年前

小A是某个创业团队的前端工程师,负责编写项目的Javascript程序。

全局变量冲突

根据自己的经验,小A先把一些常用的功能抽出来,写成函数放到一个公用文件base.js中:

var _ = {
	$: function(id) { return document.getElementById(id); },
	getCookie: function(key) { ... },
	setCookie: function(key, value) { ... }
};

小A把这些函数都放在_对象内,以防过多的全局变量造成冲突。他告诉团队的其他成员,如果谁想使用这些函数,只要引入base.js就可以了。

小C是小A的同事,他向小A反映:自己的页面引入了一个叫做underscore.js的类库,而且,这个类库也会占用_这个全局变量,这样一来就会跟base.js中的_冲突了。小A心想,underscore.js是第三方类库,估计不好改,但是base.js已经在很多页面铺开,不可能改。最后小A只好无奈地把underscore.js占用的全局变量改了。

此时,小A发现,把函数都放在一个名字空间内,可以减少全局变量冲突的概率,却没有解决全局变量冲突这个问题

4115次阅读,4条评论

Javascript日期类型的妙用

4年前

获取某个月份的天数

相信大家读小学的时候就知道一年十二个月各有多少天了,这里面有个特殊的存在——2月。闰年的2月有29天,非闰年的2月只有28天。估计不少人跟我一样,已经不记得闰年的规则了,这时候,下面的这个方法就派上用场了。

var date = new Date(2013, 2, 0);
date.getDate();  // 28
date = new Date(2012, 2, 0);
date.getDate();  // 29

创建Date对象时可以传入三个参数,分别是年、月(0~11,0表示一月)、日,如果日的参数为0,那创建出来的对象表示的就是上个月的最后一天,如此就可以知道上个月有多少天了。

同样的,我们也可以通过这个方法判断某年是否闰年:

function isLeapYear(year) {
	return new Date(year, 2, 0).getDate() === 29;
}
isLeapYear(2012);  // true
1289次阅读,2条评论

Sublime配置手记

4年前

最近一年都在用Notepad++进行开发,这个工具实在是有不少缺点,于是就在考虑换一个开发环境。候选者是WebStorm和Sublime。WebStorm是一个名副其实的IDE,启动慢,配置复杂,用起来非常不爽;相比起来,Sublime要轻很多,且五脏俱全。

(注:WebStorm和Sublime都是收费软件,WebStorm有一段试用期,而Sublime的未注册版偶尔会在保存的时候提示购买)

Sublime最吸引人的是其代码高亮,各种颜色搭配地完美无瑕,赏心悦目。

Sublime代码高亮

另一亮点是代码缩略图。这个功能在其他工具中从未见到过,不过实际作用并不大,主要就是实现快速跳转罢了。

15025次阅读,4条评论

Javascript Module Loader实现原理

5年前

前段时间我开始基于SeaJS开发2.0版本的JRaiser,主要目的就是把这个库模块化。结合实际开发过程中遇到的问题,我重新写了一个更符合自身需求的JRaiser Loader以代替SeaJS(另一方面也是为了亲手写一个Loader)。与SeaJS一样,JRaiser Loader也是Wrappings规范(关于AMD与Wrappings的区别,这篇文章有详细说明)的实现,主要接口也与SeaJS保持一致(但功能暂时比SeaJS少)。下面以JRaiser Loader的实现为例介绍一下Loader的实现原理。

先介绍几个术语:

  • 模块:模块化开发中的一个功能单元。它有一个唯一的Id作为标识,并可以依赖于其他模块。
  • 任务:全局require函数的回调函数。在JRaiser Loader的内部处理中,任务也是模块。
  • 就绪:当某个模块已经加载完成,并且不依赖于任何模块或者它依赖的所有模块已经就绪,这个模块就是就绪状态。

在模块化开发中,一个模块可以依赖于任意个模块,而被它依赖的模块又可以依赖于任意个其他模块。这就要求加载模块时必须一层一层把所有依赖的模块都加载进来,类似于树的遍历。由于前端动态加载JS的过程是异步的,也就是说,这是异步的遍历。在算法上,JRaiser Loader采取自顶向下的遍历方式以及自底向上的通知方式。假设有A、B、C三个模块,A依赖于B,B依赖于C。当通过加载A模块时,其加载过程如下(红色箭头部分为异步流程):

加载流程

1993次阅读,7条评论