高级函数
函数柯里化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| function curry(fn){ var args = Array.prototype.slice.call(arguments, 1); return function(){ var innerArgs = Array.prototype.slice.call(arguments); var finalArgs = args.concat(innerArgs); return fn.apply(null, finalArgs); } }
function add(num1, num2){ return num1 + num2; }
var curriedAdd = curry(add, 5); console.log(curriedAdd(3));
var curriedAdd1 = curry(add, 5, 13); console.log(curriedAdd1());
|
利用函数柯里化,可以构造出更为复杂的bind()函数。
1 2 3 4 5 6 7 8
| 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); } }
|
防篡改对象
不可扩展对象
1 2 3 4 5
| var person = { name: '2107'}; Object.preventExtensions(person);
person.age = 1; console.log(person.age);
|
调用Object.preverExtensions()方法后,就不能给person对象添加新属性和方法了,对于已有属性和方法,仍然可以修改和删除。另外使用Object.isExtensible()方法可以确定对象是否可以扩展。
1 2 3 4 5
| var person = { name: '2107'}; console.log(Object.isExtensible(person));
Object.preventExtensions(person); console.log(Object.isExtensible(person));
|
密封对象
1 2 3 4 5 6 7 8
| var person = { name: '2107'}; Object.seal(person);
person.age = 1; console.log(person.age);
delete person.name; console.log(person.name);
|
Object.isSealed()方法可以确定对象是否被密封了。
冻结对象
最严格的防止篡改级别是冻结对象。冻结的对象既不可扩展,又是密封的。
1 2 3 4 5 6 7 8 9 10 11
| var person = {name: '2107'}; Object.freeze(person);
person.age = 29; console.log(person.age);
delete person.name; console.log(person.name);
person.name = '1901'; console.log(person.name);
|
高级定时器
重复定时器
setInterval()定时器有两个问题:
1、 某些间隔会跳过;
2、 多个定时器代码执行之间的间隔可能会比预期的小。
为了避免setInterval()重复定时器的缺点,可以使用链式setTimeout()调用。
1 2 3 4
| setTimeout(function(){ //事件处理程序 setTimeout(arguments.callee, 1000); }, 1000)
|
Yielding Processes
1 2 3 4 5 6 7 8 9
| function chunk(array, process, context){ setTimeout(function(){ var item = array.shift(); prcoess.call(context, item); if(array.length > 1){ setTimout(argumenets.callee, 100); } }, 100) }
|
函数节流
第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,清除前一次的定时器,并设置另一个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| var processor = { timeoutId: null, preformProcessing: function(){ }, process: function(){ clearTimeout(this.timeoutId); var that = this; this.timoutId = setTimeout(function(){ that.performProcessing(); }, 1000) } } processor.process();
|
简化:
1 2 3 4 5 6
| function throttle(method, context){ clearTimeout(method.tId); method.tId = setTimout(function(){ method.call(context); }, 100) }
|
对于onresize:
1 2 3 4 5 6 7 8
| function resizeDiv(){ var div = document.getElementById('myDIv'); div.style.height = div.offsetWidth + 'px'; }
window.onresize = function(){ throttle(resizeDiv); }
|
自定义事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| 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]; } } }
function handlerMessage(event){ console.log('Message received: ' + event.message); }
var target = new EventTarget();
target.addHandler('message', handlerMessage);
target.fire({type:'message', message:'hello world!'});
target.removeHandler('message', handlerMessage);
target.fire({type:'message', message: 'hello world'});
|