第十八章 高级技巧 
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以上的事件完成,最好分割为一系列可以使用定时器的小任务。
③数组分块技术:为要处理的项目创建一个队列,然后使用定时器取出下一个要处理的项目进行处理,接着再设置另一个定时器。
复制代码 代码如下:
