第十八章 高级技巧
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 

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

④使用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高级技巧的更多相关文章

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

    JavaScript高级程序设计 学习笔记 js高级技巧,学习js的朋友可以参考下。

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部