高级函数
安全的类型检测,检测是原生对象还是自定义对象
Object.prototype.toString 返回构造函数名
var arr = [];
console.log(Object.prototype.toString.call(arr));//[object Array]
作用域安全的构造函数
function Person(name, age) {
if(this instanceof Person){
this.name = name;
this.age = age;
}else {
return new Person(name, age);
}
}
这样做存在的问题:当使用构造函数模式实现继承时,由于作用域安全,所以继承不能实现。
function Super(name) {
if(this instanceof Super) {
this.name = name;
}else {
return new Super(name);
}
}
function Sub(name, age) {
Super.call(this, name);
this.age = age;
}
var sub = new Sub("sub", 21);
console.log(sub.name);//undefined
为解决这个问题,可以结合原型链用组合模式实现继承,为上述代码添加: Sub.prototype = new Super();
惰性载入函数
包含大量if的语句,每次调用时分支结果都不变,如果能减少if的执行会加快速度。惰性载入函数就解决方案。
两种方式:
* 在函数被调用时处理函数
* 在声明函数时就指定适当的函数。
函数绑定
bind
函数柯里化
使函数参数单一化
防止篡改对象
- 不可扩展对象
不能给对象添加新成员,但是对已有成员不影响
Object.preventExtensions(); //禁止再给对象添加属性
Object.isExtensible();//判断对象是否可扩展 - 密封对象
被密封的对象不可扩展,且密封对象不可删除属性,[[Configureable]]设置成false
Object.seal();
Object.isSealed(); - 冻结对象
冻结对象既是不可扩展的,又是密封的,对象数据属性[[Writable]]被设置false
Object.freeze();
定时器
指定的时间间隔表示何时将定时器的代码添加到队列,而不是何时执行代码
- setTnterval()存在的问题是:定时器代码可能在代码再次添加到队列之前还没有完成执行,导致定时器代码连续运行多次,之间没有间隔。
javascript引擎避免了这个问题:当使用setInterval时,仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中。
但是setInterval()重复定时器仍然存在的两个问题:
- 某些间隔会被跳过
- 多个定时器的代码执行之间的间隔会比预期小
- 解决上述问题的方案:使用链式setTimeout()
setTimeout(function() {
// code
// arguments.callee获取当前执行的函数的引用
setTimeout(arguments.callee, 200);
}, 200);
函数节流
var processor = {
timeoutId: null,
method: function() {
console.log("sad");
},
process: function() {
clearTimeout(this.timeoutId);
var that = this;
this.timeoutId = setTimeout(function() {
that.method();
}, 100);
}
}
for(var i = 0;i < 100;i++) {
processor.process();
}
最后一次调用process()之后至少100ms后才会调用method()。所以100ms内调用process()100次,method()仍然只会调用一次。
// 简化
function throttle(method) {
clearTimeout(method.tid);
method.tid = setTimeout(function() {
method();
}, 100);
}