JavaScript惰性函数定义
函数是js世界的一等公民,js的动态性、易变性在函数的应用上,体现的淋漓尽致。做为参数,做为返回值等,正是函数这些特性,使得js开发变的有趣。
下面就阐述一下,js一个有趣的应用--惰性函数定义(Lazy Function Definition)。
惰性载入表示函数执行的分支只会在函数第一次掉用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了。
下面我们看几个典型的例子:
function addEvent (type, element, fun) {
if (element.addEventListener) {
element.addEventListener(type, fun, false);
}
else if(element.attachEvent){
element.attachEvent('on' + type, fun);
}
else{
element['on' + type] = fun;
}
}
上面是注册函数监听的各浏览器兼容函数。由于,各浏览之间的差异,不得不在用的时候做能力检测。显然,单从功能上讲,已经做到了兼容浏览器。
美中不足,每次绑定监听,都会对能力做一次检测。然而,真正的应用中,这显然是多余的,同一个应用环境中,其实只需要检测一次即可。
下面我们重写上面的addEvent:
function addEvent (type, element, fun) {
if (element.addEventListener) {
addEvent = function (type, element, fun) {
element.addEventListener(type, fun, false);
}
}
else if(element.attachEvent){
addEvent = function (type, element, fun) {
element.attachEvent('on' + type, fun);
}
}
else{
addEvent = function (type, element, fun) {
element['on' + type] = fun;
}
}
return addEvent(type, element, fun);
}
由上,第一次调用addEvent会对浏览器做能力检测,然后,重写了addEvent。下次再调用的时候,由于函数被重写,不会再做能力检测。
同样的应用,javascript高级程序设计里的一例子:
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"];
for (var i=0,len=versions.length; i < len; i++){
try {
var xhr = new ActiveXObject(versions[i]);
arguments.callee.activeXString = versions[i];
return xhr;
} catch (ex){
//skip
}
}
}
return new ActiveXObject(arguments.callee.activeXString);
} else {
throw new Error("No XHR object available.");
}
}
很显然,惰性函数在这里优势更加明显,因为这里有更多的分支。下面我们看一下重写后台的函数:
function createXHR() {
if (typeof XMLHttpRequest != "undefined") {
createXHR = function () {
return new XMLHttpRequest();
}
return new XMLHttpRequest();
} else if (typeof ActiveXObject != "undefined") {
var curxhr;
var versions = ["MSXML2.XMLHttp.6.0", "MSXML2.XMLHttp.3.0",
"MSXML2.XMLHttp"];
for (var i = 0, len = versions.length; i < len; i++) {
try {
var xhr = new ActiveXObject(versions[i]);
curxhr = versions[i];
createXHR = function () {
return new ActiveXObject(curxhr);
}
return xhr;
} catch (ex) {
//skip
}
}
} else {
throw new Error("No XHR object available.");
}
}
浏览器之间最大的差异,莫过于Dom操作,Dom操作也是前端应用 中最频繁的操作,前端的大多性能提升,均体现在Dom操作方面。
下面看一个Dom操作方面的惰性函数定义例子:
var getScrollY = function() {
if (typeof window.pageYOffset == 'number') {
getScrollY = function() {
return window.pageYOffset;
};
} else if ((typeof document.compatMode == 'string') &&
(document.compatMode.indexOf('CSS') >= 0) &&
(document.documentElement) &&
(typeof document.documentElement.scrollTop == 'number')) {
getScrollY = function() {
return document.documentElement.scrollTop;
};
} else if ((document.body) &&
(typeof document.body.scrollTop == 'number')) {
getScrollY = function() {
return document.body.scrollTop;
}
} else {
getScrollY = function() {
return NaN;
};
}
return getScrollY();
}
惰性函数定义应用还体现在创建单例上:
unction Universe() {
// 缓存的实例
var instance = this;
// 其它内容
this.start_time = 0;
this.bang = "Big";
// 重写构造函数
Universe = function () {
return instance;
};
}
当然,像上面这种例子有很多。惰性函数定义,应用场景我们可以总结一下:
1 应用频繁,如果只用一次,是体现不出它的优点出来的,用的次数越多,越能体现这种模式的优势所在;
2 固定不变,一次判定,在固定的应用环境中不会发生改变;
3 复杂的分支判断,没有差异性,不需要应用这种模式;
JavaScript惰性函数定义的更多相关文章
- javascript 回调函数定义 模板
函数定义: function callfun(in_param,callback) { console.log(in_param); var out_param='bbbbb'; return (ty ...
- javascript惰性函数
惰性函数:所谓惰性函数就是创建了一个新函数并且将其分配给保存了另外函数的同一个变量,就以一个新函数覆盖了旧函数.某种程度上,回收了旧函数指针以指向一个新函数. 板栗: var scareMe = fu ...
- javascript . 03 函数定义、函数参数(形参、实参)、函数的返回值、冒泡函数、函数的加载、局部变量与全局变量、隐式全局变量、JS预解析、是否是质数、斐波那契数列
1.1 知识点 函数:就是可以重复执行的代码块 2. 组成:参数,功能,返回值 为什么要用函数,因为一部分代码使用次数会很多,所以封装起来, 需要的时候调用 函数不调用,自己不会执行 同名函数会覆盖 ...
- JavaScript函数定义和调用 变量作用域
本文是笔者在看廖雪峰老师JavaScript教程时的个人总结 JavaScript中函数定义可以是这样的格式 function 函数名(参数) { 函数体 } 也可以是这样的格式 ...
- 【JavaScript】函数
No1: 定义函数 function abs(x) { if (x >= 0) { return x; } else { return -x; } } var abs = function (x ...
- JavaScript之惰性函数
前不久看到javascript的性能优化的这里,有关惰性函数 假如同一个函数有许多判断来检测函数,而我们每一次调用,都会判断检测函数 例如: function addEvent (type, elem ...
- 深入理解javascript函数定义与函数作用域
最近在学习javascript的函数,函数是javascript的一等对象,想要学好javascript,就必须深刻理解函数.本人把思路整理成文章,一是为了加深自己函数的理解,二是给读者提供学习的途径 ...
- JavaScript要点 (五) 函数定义
JavaScript 使用关键字 function 定义函数. 函数可以通过声明定义,也可以是一个表达式. 函数声明分号是用来分隔可执行JavaScript语句. 由于函数声明不是一个可执行语句,所以 ...
- javascript函数定义表达式和函数声明的区别
在javascript中,函数有两种定义写法,函数定义表达式和函数声明,其例子分别如下所示: var test = function(x){ return x; } function test(x){ ...
随机推荐
- LINUX修改、增加IP的方法,一张网卡绑定多个IP/漂移IP【转】
临时增加IP命令:ifconfig eth0:1 ip地址 netmask 子网码 broadcast 广播地址 gateway 网关 ifconfig eth0:1 10.1.104.65 net ...
- MySQL 联合查询
联合查询:将多次查询(多条select语句), 在记录上进行拼接(字段不会增加) 基本语法:多条select语句构成: 每一条select语句获取的字段数必须严格一致(但是字段类型无关) 语法 Sel ...
- Go 的package
一.包的一些基本的概念 1.在同一个目录下的所有go文件中,只能有一个main函数.如果存在多个main函数,则在编译的时候会报错 那么,在同一个目录下的两个go文件究竟是什么关系? 为什么会彼此影响 ...
- SQLAlchemy-方言(Dialects)
一: Dialects 文档是分为三个部分: SQLAlchemy ORM, SQLAlchemy Core, and Dialects. SQLAlchemy ORM:在SQLAlchemy ORM ...
- 洛谷P1168中位数
传送门啦 基本思想就是二分寻找答案,然后用树状数组去维护有几个比这个二分出来的值大,然后就没有了: 数据要离散,这个好像用map也可以,但是不会: 那怎么离散呢? 我们先把a数组读入并复制给s数组,然 ...
- Luogu P3384 【【模板】树链剖分】
转载请注明出处,部分内容引自banananana大神的博客 ~~别说你不知道什么是树~~╮(─▽─)╭(帮你百度一下) 先来回顾两个问题:1,将树从x到y结点最短路径上所有节点的值都加上z 这也是个模 ...
- elasticsearch学习笔记--原理介绍
前言:上一篇中我们对ES有了一个比较大概的概念,知道它是什么,干什么用的,今天给大家主要讲一下他的工作原理 介绍:ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户 ...
- Unix IPC之FIFO
#include "unpipc.h" #define FIFO1 "/tmp/fifo.1" #define FIFO2 "/tmp/fifo.2& ...
- Centos之命令搜索命令whereis与which
Centos之命令搜索命令whereis与which whereis 命令名 #搜索命令所在路径及帮助文档所在位置 选项: -b :只查找可执行文件位置 -m:只查找帮助文件 [root@localh ...
- Java输出文件到本地(输出流)
package cn.buaa; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; im ...