JavaScript高级程序设计 学习笔记 js高级技巧


Posted in Javascript onSeptember 20, 2011

第十八章 高级技巧
1.高级函数
1.1 作用域安全的构造函数
①直接调用构造函数而不适用new操作符时,由于this对象的晚绑定,它将映射在全局对象window上,导致对象属性错误增加到window。

function Person(name,age,job){ 
this.name = name; 
this.age = age; 
this.job = job; 
} 
Var person = Person("Jay",29,"singer"); //属性增加到window对象上。

②作用域安全构造函数
function Person(name,age,job){ 
if(this instanceof Person){ 
this.name = name; 
this.age = age; 
}else{ 
return new Person(name,age); 
} 
}

③上述作用域安全的构造函数,如果使用构造函数窃取模式的继承且不使用原型链,那么这个继承很可能被破坏。
□如果构造函数窃取结合使用原型链或者寄生式组合则可以解决这个问题。
function Polygon(side){ 
if(this instanceof Polygon){ 
this.sides = sides; 
this.getArea = function{return 0;}; 
}else{ 
return new Polygon(sides); 
} 
} 
function Rectangle(width,height){ 
Polygon.call(this,2); 
this.width = width; 
this.height = height; 
this.getArea = function(){ 
return this.width * this.height; 
}; 
} 
Rectangle.prototype = new Polygon(); 
var rect = new Rectangle(5,10); 
alert(rect.sides); //2

1.2 惰性载入函数
①惰性载入表示函数执行的分支仅会发生一次:既第一次调用的时候。在第一次调用的过程中,该函数会被覆盖为另一个按合适方式执行的函数,这样任何对原函数的调用都不用再经过执行的分支了。
■优点:
□要执行的适当代码只有当实际调用函数时才进行。
□尽管第一次调用该函数会因额外的第二个函数调用而稍微慢点,但后续的调用都会很快,因避免了多重条件。
function create XHR(){ 
if(typeof XMLHttp Request != "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"]; 
for(vai I = 0, len = versions.length; I < len; i++){ 
try{ 
Var xhr = new ActiveXObject(version[i]); 
Arguments.callee.activeXString = version[i]; 
Return xhr; 
}catch(ex){ 
//skip 
} 
} 
} 
return new ActiveXObject(arguments.callee.activeXString); 
}; 
}else{ 
createXHR = function(){ 
throw new Error("No XHR Object available."); 
}; 
} 
return createXHR(); 
}

1.3 函数绑定
①函数绑定要创建一个函数,可以在特定环境中以指定参数调用另一个函数。
②一个简单的bind()函数接受一个函数和一个环境,并返回一个在给定环境中调用给定函数的函数,并且将所有参数原封不动传递过去。
function bind(fn, context){ 
return function(){ 
return fn.apply(context, arguments); 
}; 
}

③被绑定函数与普通函数相比有更多的开销——它们需要更多内存,同时也因为多重函数调用而稍微慢一点——所以最好只在必要时使用。
1.4 函数柯里化
定义:用于创建已经设置好了一个或多个参数的函数。函数柯里化的基本方法和函数绑定是一样的:使用一个闭包返回一个函数。两者的区别在于,当函数被调用时,返回函数还需要设置一些传入的参数。
function bind(fn, context){ 
var args = Array.prototype.slice.call(arguments, 2); 
return function(){ 
var innerArgs = Array.prototype.slice.call(arguments); 
var finalArgs = args.concat(innerArgs); 
return fn.apply(context,finalArgs); 
}; 
}

2.高级定时器
①JavaScript是单线程程序,定时器是在间隔时间后将代码添加到列队。
②执行完一套代码后,JavaScript进程返回一段很短的时间,这样页面上的其他处理就可以进行了。
2.1 重复的定时器
①setInterval()仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中。
□某些间隔会被跳过。
□多个定时器代码执行之间的间隔可能会比预期小。
②避免setInterval()的两个缺点,使用链式setTimeout()调用:
setTimeout(function(){ 
//处理 
if(condition){ 
setTimeout(arguments.callee, interval); 
} 
},interval);

2.2 Yielding Processes
①JavaScript长时间运行脚本制约:如代码运行超过特定的时间或特定的语句数量就不会让它继续执行。
②当某个函数要花200ms以上的事件完成,最好分割为一系列可以使用定时器的小任务。
③数组分块技术:为要处理的项目创建一个队列,然后使用定时器取出下一个要处理的项目进行处理,接着再设置另一个定时器。
function chunk(array, process, context){ 
setTimeout(function(){ 
var item = array.shift(); 
process.call(context,item); 
if(array.length>0){ 
setTimeout(arguments.callee, 100); 
} 
} 
}

2.3 函数节流
①DOM操作比起非DOM交互需要更多内存和CPU时间。连续尝试进行过多的DOM相关操作可能会导致浏览器挂起,有时甚至崩溃。
②函数节流思想:某些代码不可以在没有间断的情况连续重复执行。
□示例
var processor = { 
timeoutId : null, 
//实际进行处理的方法 
performProcessing : function(){ 
//实际执行的方法 
}, 
//初始处理调用的方法 
process : function(){ 
clearTimeout(this.timeoutId); 
var that = this; 
this.timeoutId = setTimeout(function(){ 
that.performProcessing(); 
},100); 
} 
}; 
//尝试开始执行 
Processor.process(); 
□简化模式 
function throttle(method,context){ 
clearTimeout(mehtod.tId); 
mehtod.tId = setTimeout(function(){ 
method.call(context); 
},100); 
}

3.自定义事件
①事件是一种叫做观察者的设计模式,这是一种创建松散耦合代码的技术。
□对象可以发布事件,用来表示该对象声明周期中某个有趣的时刻到了。
□其他对象可以观察该对象,等待有趣的时刻到来并通过运行代码来响应。
②观察者模式由两类对象组成:主体和观察者。
□主体负责发布事件,同时观察者通过订阅这些事件来观察主体。
□主体并不知道观察者的任何事情,它可以独立自存在并正常运作即使观察者不在。
③自定义事件:创建一个管理事件的对象,让其他对象监听那些事件。
function EventTarget(){ 
this.handlers = {}; 
} 
EventTarget.prototype = { 
constructor : EventTarget, 
addHandler : function(type,handler){ 
if(typeof this.handlers[type] == "undefined"){ 
this.handlers[type] = []; 
} 
this.handlers[type].push(handler); 
}, 
fire : function(event){ 
if(!event.target){ 
event.target = this; 
} 
if(this.handlers[event.type] instanceof Array){ 
var handlers = this.handlers[event.type]; 
for(var i=0,len=handlers.length; i<len; i++){ 
handlers[i](event); 
} 
} 
}, 
removeHandler : function(type, handler){ 
if(this.handlers[type] instanceof Array){ 
var handlers = this.handlers[type]; 
for(var i=0,len=handlers.length; i<len; i++){ 
if(handlers[i] === handler){ 
break; 
} 
} 
Handlers.splice(i,1); 
} 
};

④使用EventTarget类型的自定义事件可以如下使用:
function handleMessage(event){ 
alert("message received:" + event.message); 
} 
//创建一个新对象 
var target = new EventTarget(); 
//添加一个事件处理程序 
target.addHandler("message",handleMessage); 
//触发事件 
target.fire({type:"message",message:"hello world!"}); 
//删除事件处理程序 
target.removeHandler("message",handleMessage);

⑤使用实例
function Person(name,age){ 
eventTarget.call(this); 
this.name = name; 
this.age = age; 
} 
inheritPrototype(Person, EventTarget); 
Person.prototype.say = function(message){ 
this.fire({type:"message", message:message}); 
}; 
function handleMessage(event){ 
alert(event.target.name + "says: " + event.message); 
} 
//创建新person 
var person = new Person("Nicholas",29); 
//添加一个事件处理程序 
Person.addHandler("message",handleMessage); 
//在该对象上调用1个方法,它触发消息事件 
person.say("Hi there");

4.拖放
功能:①拖放②添加了自定义事件
var DragDrop = function(){ 
var dragdrop = new EventTarget(); 
var dragging = null; 
var diffX = 0; 
var diffY = 0; 
function handleEvent(event){ 
//获取事件和对象 
event = EventUtil.getEvent(event); 
var target = EventUtil.getTarget(event); 
//确定事件类型 
switch(event.type){ 
case "mousedown" : 
if(target.className.indexOf("draggable")>-1){ 
dragging = target; 
diffX = event.clientX - target.offsetLeft; 
diffY = event.clientY - target.offsetTop; 
dragdorp.fire( 
{ 
type:"dragstart", 
target : dragging, 
x : event.clientX, 
y : event.clientY 
} 
); 
break; 
case "mousemove" : 
if(dragging !== null){ 
//获取事件 
event = EventUtil.getEvent(event); 
//指定位置 
dragging.style.left = (event.clientX - diffX) + "px"; 
dragging.style.top = (event.clientY - diffY) + "px"; 
//触发自定义事件 
dragdrop.fire( 
{ 
type : "drag", 
target : dargging, 
x : event.clientX, 
y : event.clientY 
} 
); 
} 
break; 
case "mouseup" : 
dargdorp.fire( 
{ 
type : "dragend", 
target : dragging, 
x : event.clientX, 
y : event.clientY 
} 
); 
dragging = null; 
break; 
} 
} 
//公共接口 
dragdrop.enable = function() { 
EventUtil.addHandler(document, "mousedown", handleEvent); 
EventUtil.addHandler(document, "mousemove", handleEvent); 
EventUtil.addHandler(document, "mouseup", handleEvent); 
}; 
dragdrop.disable = function(){ 
EventUtil.removeHandler(document, "mousedown", handleEvent); 
EventUtil.removeHandler(document, "mousemove", handleEvent); 
EventUtil.removeHandler(document, "mouseup", handleEvent); 
}; 
return dragdrop; 
}();
Javascript 相关文章推荐
javascript获取设置div的高度和宽度兼容任何浏览器
Sep 22 Javascript
Script标签与访问HTML页面详解
Jan 10 Javascript
jQuery对象初始化的传参方式
Feb 26 Javascript
JavaScript实现的encode64加密算法实例分析
Apr 15 Javascript
Ajax清除浏览器js、css、图片缓存的方法
Aug 06 Javascript
前端学习笔记style,currentStyle,getComputedStyle的用法与区别
May 28 Javascript
Vuejs 用$emit与$on来进行兄弟组件之间的数据传输通信
Feb 23 Javascript
基于three.js编写的一个项目类示例代码
Jan 05 Javascript
详解使用create-react-app快速构建React开发环境
May 16 Javascript
vue vue-Router默认hash模式修改为history需要做的修改详解
Sep 13 Javascript
推荐15个最好用的JavaScript代码压缩工具
Feb 13 Javascript
Vue 前端实现登陆拦截及axios 拦截器的使用
Jul 17 Javascript
跨浏览器通用、可重用的选项卡tab切换js代码
Sep 20 #Javascript
JQuyer $.post 与 $.ajax 访问WCF ajax service 时的问题需要注意的地方
Sep 20 #Javascript
简单的jquery拖拽排序效果实现代码
Sep 20 #Javascript
用jQuery中的ajax分页实现代码
Sep 20 #Javascript
jquery模拟按下回车实现代码
Sep 20 #Javascript
一个分享按钮的插件使用介绍(可扩展,内附开发制作流程)
Sep 19 #Javascript
50个比较实用jQuery代码段
Sep 18 #Javascript
You might like
PHP利用REFERER根居访问来地址进行页面跳转
2013/09/28 PHP
优化JavaScript脚本的性能的几个注意事项
2006/12/22 Javascript
IE7提供XMLHttpRequest对象为兼容
2007/03/08 Javascript
百度 popup.js 完美修正版非常的不错 脚本之家推荐
2009/04/17 Javascript
jquery.validate使用攻略 第二部
2010/07/01 Javascript
页面回到顶部的三种实现(锚标记,js)
2012/10/01 Javascript
jQuery不使用插件及swf实现无刷新文件上传
2014/12/08 Javascript
js漂浮广告实现代码
2015/08/15 Javascript
Nodejs Express4.x开发框架随手笔记
2015/11/23 NodeJs
基于JavaScript的操作系统你听说过吗?
2016/01/28 Javascript
iframe中使用jquery进行查找的方法【案例分析】
2016/06/17 Javascript
jQuery实现的兼容性浮动层示例
2016/08/02 Javascript
基于d3.js实现实时刷新的折线图
2016/08/03 Javascript
$.browser.msie 为空或不是对象问题的多种解决方法
2017/03/19 Javascript
CodeMirror js代码加亮使用总结
2017/03/25 Javascript
微信小程序picker组件下拉框选择input输入框的实例
2017/09/20 Javascript
详解ionic本地相册、拍照、裁剪、上传(单图完全版)
2017/10/10 Javascript
VUE2 前端实现 静态二级省市联动选择select的示例
2018/02/09 Javascript
谈谈JavaScript中的函数
2020/09/08 Javascript
[00:59]DOTA2背景故事第二期之四大基本法则
2020/07/07 DOTA
python encode和decode的妙用
2009/09/02 Python
python实现多线程的方式及多条命令并发执行
2016/06/07 Python
python使用正则表达式的search()函数实现指定位置搜索功能
2017/11/10 Python
Python实现修改文件内容的方法分析
2018/03/25 Python
资生堂英国官网:Shiseido英国
2020/12/30 全球购物
高中自我鉴定
2013/12/20 职场文书
大学生职业生涯设计书
2014/01/02 职场文书
秋天的雨教学反思
2014/04/27 职场文书
教师演讲稿开场白
2014/08/25 职场文书
2014教师“四风问题”对照检查材料思想汇报
2014/09/16 职场文书
三八妇女节标语
2014/10/09 职场文书
农民工工资保障承诺书
2015/05/04 职场文书
学会Python数据可视化必须尝试这7个库
2021/06/16 Python
MySQL 主从复制数据不一致的解决方法
2022/03/18 MySQL
python基础之//、/与%的区别详解
2022/06/10 Python
Win11运行cmd提示“请求的操作需要提升”的两种解决方法
2022/07/07 数码科技