读书笔记:javascript高级技巧(二)
四。惰性载入函数
因为浏览器兼容的原因,我们的javascript代码会有大量的if语句,将执行引导到正确的代码中,看如下函数:
function createXHR(){
if (typeof XMLHttpRequest != "undefined"){
return new XMLHttpRequest();
} else if (typeof ActiveXObject != "undefined"){
if (typeof arguments.callee.activeXString != "string"){
var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"],
i, len; for (i=0,len=versions.length; i < len; i++){
try {
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
} catch (ex){
//skip
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
} else {
throw new Error("No XHR object available.");
}
}
每次在调用createXHR时,都要对浏览器支持的能力进行检查。如果多次调用,这种检查就没有必要了。如果if语句不必每次执行,那么代码可以运行的更快一些。解决方案就是称之为惰性载入的技巧。
惰性载入表示函数执行的分支仅会发生一次。有两种实现惰性载入的方式。第一种就是在函数被调用时再处理函数:在第一次调用的过程中,该函数会被覆盖为另外一个按合适方式执行的函数,这样任何对原函数的调用都不用再经过执行分支。第二种是在声明函数时就指定适当的函数:这样第一次调用时就不会损失性能力,而在代码首次加载时会损失一点性能。具体看码~
1.在函数被调用时再处理函数
function createXHR(){
if (typeof XMLHttpRequest != "undefined"){
createXHR = function(){
return new XMLHttpRequest();
};
} else if (typeof ActiveXObject != "undefined"){
createXHR = function(){
if (typeof arguments.callee.activeXString != "string"){
var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"],
i, len; for (i=0,len=versions.length; i < len; i++){
try {
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
} catch (ex){
//skip
}
}
} return new ActiveXObject(arguments.callee.activeXString);
};
} else {
createXHR = function(){
throw new Error("No XHR object available.");
};
} return createXHR();
} var xhr1 = createXHR();
var xhr2 = createXHR();
在第一次调用函数时会再处理函数,根据不同条件重写函数,这样在以后的调用中会直接调用新重写的函数而不用经过重重判断。
2.在声明函数时就指定适当的函数
var createXHR = (function(){
if (typeof XMLHttpRequest != "undefined"){
return function(){
return new XMLHttpRequest();
};
} else if (typeof ActiveXObject != "undefined"){
return function(){
if (typeof arguments.callee.activeXString != "string"){
var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"],
i, len; for (i=0,len=versions.length; i < len; i++){
try {
new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
break;
} catch (ex){
//skip
}
}
} return new ActiveXObject(arguments.callee.activeXString);
};
} else {
return function(){
throw new Error("No XHR object available.");
};
}
})(); var xhr1 = createXHR();
var xhr2 = createXHR();
//自执行匿名函数语法:(function(){})() 最开始看不懂这高大上的写法,原来是自执行函数~~~
这种方式类似于第一种,思路水样的,不同的就是第一行代码,新增了自执行的匿名函数,另外每个分支都返回正确的函数定义,以便立即将其复制给createXHR()。
五。函数柯里化
在计算机科学中,柯里化(英语:Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家哈斯凯尔·加里命名的,尽管它是 Moses Schönfinkel 和 Gottlob Frege 发明的。
这是来自维基百科的名词解释。顾名思义,柯里化其实本身是固定一个可以预期的参数,并返回一个特定的函数,处理批特定的需求。这增加了函数的适用性,但同时也降低了函数的适用范围。
理解起来比较困难,下面看实例:
function curry(fn){
var args = Array.prototype.slice.call(arguments, 1); //获取第一个参数之后的所有参数
return function(){
var innerArgs = Array.prototype.slice.call(arguments), //获取内部函数的所有参数
finalArgs = args.concat(innerArgs); //组合
return fn.apply(null, finalArgs); //没有考虑到执行环境,所以apply()第一个参数为null
};
} function add(num1, num2){
return num1 + num2;
} var curriedAdd = curry(add, 5); //创建了第一个参数绑定为5的柯里化版本
alert(curriedAdd(3)); //8 //传入第二个参数,调用add方法,相当于add(5,3) var curriedAdd2 = curry(add, 5, 12);
alert(curriedAdd2()); //
函数柯里化还常常作为函数绑定的一部分包含在其中,构造出更为复杂的bind()函数;
function bind(fn, context){
var args = Array.prototype.slice.call(arguments, 2);
return function(){
var innerArgs = Array.prototype.slice.call(arguments),
finalArgs = args.concat(innerArgs);
return fn.apply(context, finalArgs);
};
} var handler = {
message: "Event handled", handleClick: function(name, event){
alert(this.message + ":" + name + ":" + event.type);
}
}; var btn = document.getElementById("my-btn");
EventUtil.addHandler(btn, "click", bind(handler.handleClick, handler, "my-btn"));
读书笔记:javascript高级技巧(二)的更多相关文章
- 《Linux内核设计与实现》读书笔记——第一、 二章
<Linux内核设计与实现>读书笔记--第一. 二章 标签(空格分隔): 20135321余佳源 第一章 Linux内核简介 1.Unix内核特点 十分简洁:仅提供几百个系统调用并且有明确 ...
- 《Linux内核设计与实现》读书笔记(十二)- 内存管理【转】
转自:http://www.cnblogs.com/wang_yb/archive/2013/05/23/3095907.html 内核的内存使用不像用户空间那样随意,内核的内存出现错误时也只有靠自己 ...
- 《android开发艺术探索》读书笔记(十二)--Bitmap的加载和Cache
接上篇<android开发艺术探索>读书笔记(十一)--Android的线程和线程池 No1: 目前比较常用的缓存策略是LruCache和DiskLruCache,LruCache常被用作 ...
- 读书笔记-JavaScript面向对象编程(二)
第5章 原型 5.1 原型属性(所有函数拥有一个prototype属性,默认为空对象) 5.1.1 利用原型添加方法和属性 function Gadget(name,color){ this.name ...
- [读书笔记]javascript语言精粹'
人比较笨,以前只做项目,案例,然而一些javascript的很多理论不知道该怎么描述,所以最近开启一波读书之旅: 标识符 1.定义 标识符以字母开头,可能后面跟上一个或多个字母.数字或者下划线. 2. ...
- JS高程读书笔记-第一、二章-内附在线思维导图和quizlet卡片
之前在kindle上买了高程,今天又到了纸质的<JavaScript语言精粹>,<高性能JavaScript>,<JavaScipt设计模式>,开始读书之旅啦. 我 ...
- 《JavaScript权威指南》读书笔记——JavaScript核心
前言 这本由David Flanagan著作,并由淘宝前端团队译的<JavaScript权威指南>,也就是我们俗称的“犀牛书”,算是JS界公认的“圣经”了.本书较厚(有1004页),读起来 ...
- [读书笔记] JavaScript设计模式: 单例模式
单例模式:保证一个类只有一个实例,并提供一个可以访问它的全局访问点. 一种简单.方便的写法就是用一个变量来标识当前类是否已经创建过对象,如果有,则返回已经创建好的对象,否则创建一个新对象,并将其返回. ...
- <读书笔记>JavaScript系列之7种创建对象(面向对象)
写在前面: 以下三选一: 阅读博文JavaScript 对象详解. 阅读<JavaScript权威指南>第6章. 阅读<JavaScript高级程序设计>第6章. 注意:只需要 ...
- 读书笔记-----javascript基本数据类型
由于js基础差, 记性也不好,准备一边读书一边做记录,希望这样能加深一下记忆 /* 第一天 */ javascript 基本数据类型 js一共只有五种数据类型 Undefined, Nu ...
随机推荐
- SQLServer内置函数
类型转换函数cast和convert --cast一般更容易使用,convert的优点是可以格式化日期和数值 select CAST('123.4' as int) --失败 select CONVE ...
- jQuery ajax同步的替换方法,使用 $.Deferred()对象
function aa() { var defer = $.Deferred(); $.ajax({ url: "/Handler1.ashx", type: "post ...
- java 泛型 -- 泛型类,泛型接口,泛型方法
泛型T泛型的许多最佳例子都来自集合框架,因为泛型让您在保存在集合中的元素上指定类型约束.在定义泛型类或声明泛型类的变量时,使用尖括号来指定形式类型参数.形式类型参数与实际类型参数之间的关系类似于形式方 ...
- Win10 创建应用程序包及部署
https://msdn.microsoft.com/zh-cn/library/windows/apps/xaml/hh454036.aspx https://msdn.microsoft.com/ ...
- 实现Activity刷新 (转)
目前刷新Acitivity,只想到几种方法.仅供参考,如果您有更好的方法,请赐教. 程序界面: 点击refresh view可以刷新界面,点击write content可以在EditText中自动写入 ...
- POJ 1947 Rebuilding Roads 树形DP
Rebuilding Roads Description The cows have reconstructed Farmer John's farm, with its N barns (1 & ...
- WEB前端知识体系脑图
说在开始的话: 我上大学那会,虽说主要是学Java语言,但是web前端也稍微学了一些,那时候对前端也没多在意,因为涉入的不深,可以搞一个差不多可以看的界面就可以了,其他也没过多在意. 因为稍微了解一点 ...
- LoadRunner 事务函数
status 包括LR_PASS, LR_FAIL, LR_AUTO, LR_STOP(这个没用过) lr_set_transaction_instance_status(status); 可以根 ...
- SQL单表查询案例
表(emp)结构 (1)查询部门编号为10中所有经理,部门编号为20中所有销售员,还有即不是经理又不是销售员但其工资大或等于20000的所有员工详细资料. SELECT * FROM emp ; (2 ...
- python特殊函数 __call__()
__call__ 在Python中,函数其实是一个对象: >>> f = abs >>> f.__name__ 'abs' >>> f(-123) ...