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 相关文章推荐
js静态作用域的功能。
Dec 25 Javascript
Js setInterval与setTimeout(定时执行与循环执行)的代码(可以传入参数)
Jun 11 Javascript
加载jQuery后$冲突的解决办法
Jul 09 Javascript
php显示当前文件所在的文件以及文件夹所有文件以树形展开
Dec 13 Javascript
在JavaScript中重写jQuery对象的方法实例教程
Aug 25 Javascript
基于jQuery1.9版本如何判断浏览器版本类型
Jan 12 Javascript
只需五句话搞定JavaScript作用域(经典)
Jul 26 Javascript
JS实现动画兼容性的transition和transform实例分析
Dec 13 Javascript
微信小程序 开发之滑块视图容器(swiper)详解及实例代码
Feb 22 Javascript
Angularjs中date过滤器失效的问题及解决方法
Jul 06 Javascript
ES6知识点整理之模块化的应用详解
Apr 15 Javascript
vue keep-alive列表页缓存 详情页返回上一页不刷新,定位到之前位置
Nov 26 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 中使用ajax时一些常见错误总结整理
2017/02/27 PHP
php制作圆形用户头像的实例_自定义封装类源代码
2017/09/18 PHP
javascript之对系统的toFixed()方法的修正
2007/05/08 Javascript
Prototype Number对象 学习
2009/07/19 Javascript
javascript中&quot;/&quot;运算符常见错误
2010/10/13 Javascript
关于二级域名下使用一级域名下的COOKIE的问题
2011/11/07 Javascript
jQuery中需要注意的细节问题小结
2011/12/06 Javascript
异步动态加载JS并运行(示例代码)
2013/12/13 Javascript
jquery无限级联下拉菜单简单实例演示
2015/11/23 Javascript
教你一步步用jQyery实现轮播器
2016/12/18 Javascript
基于 Vue.js 2.0 酷炫自适应背景视频登录页面实现方式
2018/01/17 Javascript
JS实现json对象数组按对象属性排序操作示例
2018/05/18 Javascript
微信小程序日期选择器实例代码
2018/07/18 Javascript
深入浅出 Vue 系列 -- 数据劫持实现原理
2019/04/23 Javascript
Vue实现 点击显示再点击隐藏效果(点击页面空白区域也隐藏效果)
2020/01/16 Javascript
JS实现横向轮播图(中级版)
2020/01/18 Javascript
Python常用正则表达式符号浅析
2014/08/13 Python
python获取本机外网ip的方法
2015/04/15 Python
浅谈Python中的闭包
2015/07/08 Python
Selenium的使用详解
2018/10/19 Python
对python当中不在本路径的py文件的引用详解
2018/12/15 Python
python游戏开发之视频转彩色字符动画
2019/04/26 Python
python查看文件大小和文件夹内容的方法
2019/07/08 Python
Python实现计算长方形面积(带参数函数demo)
2020/01/18 Python
django 读取图片到页面实例
2020/03/27 Python
在ipython notebook中使用argparse方式
2020/04/20 Python
python regex库实例用法总结
2021/01/03 Python
Python实现邮件发送的详细设置方法(遇到问题)
2021/01/18 Python
HTML5之SVG 2D入门8—文档结构及相关元素总结
2013/01/30 HTML / CSS
中学生期末评语
2014/02/03 职场文书
村委会换届选举方案
2014/05/03 职场文书
装饰工程师岗位职责
2014/06/08 职场文书
开发房地产协议书
2014/09/14 职场文书
培训心得体会怎么写
2016/01/25 职场文书
血轮眼轮回眼特效 html+css
2021/03/31 HTML / CSS
MySQL读取JSON转换的方式
2022/03/18 MySQL