第3章闭包和高阶函数
3.1闭包
3.1.1 变量的作用域
3.1.2 变量的生存周期
var Type = {};
for(var i = 0, type; type = ['String','Array','Number'][i++];){
(function(type){
Type['is'+type] = function(obj){
return Object.prototype.toString.call(obj) === '[object '+type+']';
}
})(type)
}
var a = Type.isArray([]);//true
var b = Type.isString('str');//true
console.log(a);
console.log(b);
3.1.3 闭包的更多作用
1封装变量
var mult = (function(){
var cache = {};
var calculate = function(){
for(var i = 0, l = arguments.length; i<1; i++){
a = a*arguments[i];
}
return a;
};
return function(){
var args = Array.pototype.join.call(arguments,',');
if(args in cache){
return cache[args];
}
return cache[args] = calculate.apply(null,arguments);
}
})()
2延续局部变量的寿命
3.1.4 闭包和面向对象设计
var extent = function(){
var value = 0;
return {
call : function(){
value++;
console.log(value);
}
}
}
var extent = extent();
extent.call();
extent.call();
extent.call();
//面向对象的写法
var extent = {
value:0,
call:function(){
this.value++;
console.log(this.value);
}
}
extent.call();//1
extent.call();//2
extent.call();//3
//或者
var Exent = function(){
this.value = 0;
}
Exent.prototype.call = function(){
this.value+;
console.log(this.value);
}
var extent = new Exent;
extent.call();//1
extent.call();//2
extent.call();//3
3.1.5用闭包实现命令模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<button id="execute">点击我执行命令</button>
<button id="undo">点击我执行命令</button>
<script>
var Tv = {
open:function(){
console.log("打开电视");
},
close:function(){
console.log("关上电视")
}
};
var OpenTvCommand = function(receiver){
this.receiver = receiver;
}
OpenTvCommand.prototype.execute = function(){
this.receiver.open();
}
OpenTvCommand.prototype.undo = function(receiver){
this.receiver.close();
}
var setCommand = function(command){
document.getElementById('execute').onclick = function(){
command.execute();
}
document.getElementById('undo').onclick = function(){
command.undo();
}
};
setCommand(new OpenTvCommand(Tv));
//把请求封装为对象,从而分离请求的发起者和请求的接收者(执行者)之间的耦合关系
</script>
</body>
</html>
闭包版本
var Tv = {
open:function(){
console.log('打开电视');
},
close:function(){
console.log('关上电视');
}
};
var createCommand = function(receiver){
var execute = function(){
return receiver.open();
}
var undo = function(){
return receiver.close();
}
return {
execute:execute,
undo:undo
}
};
var setCommand = function(command){
document.getElementById('execute').onclick = function(){
command.execute();
}
document.getElementById('undo').onclick = function(){
command.undo();
}
};
setCommand(createCommand(Tv));
3.1.3 闭包与内存管理
C++以COM对象的方式实现BOM和DOM COM对象的垃圾收集机制采用的是以引用计数策略
把循环引用中的变量设为null
3.2 高阶函数
3.2.1函数作为参数传递
1回调函数
var appendDiv = function(){
for(var i = 0; i<100; i++){
var div = document.createElement('div');
div.innerHTML = i;
document.body.appendChild(div);
if(typeof callback === 'function'){
callback(div);
}
}
}
appendDiv(function(){
node.style.display = 'none'
});
2Array.prototype.sort
[1,4,3].sort(function(a,b){
return a-b;
}) //[1,3,4]
[1,4,3].sort(function(a,b){
return b-a;
}) //[4,3,1]
3.2.2函数作为返回值输出
1判断数据的类型
var isType = function(type) {
return function(obj){
return Object.prototype.toString.call(obj) ==='[object ' + type+']';
}
}
var isString = isType('Sting');
var isArray = isType('Array');
var isNumber = isType('Number');
console.log(isArray([1,2,3])); //true
2getSingle
var getSingle = function(fn){
var ret;
return function(){
return ret || (ret = fn.apply(this,arguments))
}
}
var getSingle = getSingle(function(){
return document.createElement('script');
})
var script1 = getSingle();
var script2 = getSingle();
console.log(script1===script2);
3.2.3高阶函数实现AOP
Function.prototype.before = function(beforefn){
var _self = this;
return function(){
beforefn.apply(this,arguments);
return _self.apply(this,arguments);
}
}
Function.prototype.after = function(afterfn){
var _self = this;
return function(){
var ret = _self.apply(this,arguments);
afterfn.apply(this,arguments);
return ret;
}
};
var func = function(){
console.log(2);
}
func = func.before(function(){
console.log(1);
}).after(function(){
console.log(3);
});
func();