闭包的基础是作用域即作用域链
作用域
作用域是指程序源代码中定义这个变量的区域.全局变量拥有全局作用域,在程序中始终是有定义的.局部变量有局部作用域,在函数体内及所嵌套的函数内是有定义的.函数的参数是局部变量,它的作用域在函数体内
作用域链
作用域链是一个对象列表或者链表,这组对象定义了一段码的作用域中的变量.
当javascript查找一个变量x的值时,从链表的第一个对象开始查找,如果这个对象有x属性,那么返回这个属性的值,如果第一个对象不存在x属性,接着在第二个对象查找x属性.以此类推,直到全局作用域.如果作用域链式没有任何一个对象有x属性,那么,抛出引用错误(ReferenceError)异常
闭包
一个函数通过作用域链能够读取其他函数的变量,这种特性叫做闭包
和大多数现代编程语言一样,js页采用词法作用域: 函数的执行依赖变量作用域,这个作用域是在函数定义时决定的,而不是函数调用的时候.
函数对象的内部状态不仅包含代码逻辑,还必须引用当前的作用域链.
var scope = "global scope"
function checkscope () {
var scope = "local scope"
function f() {
return scope;
}
return f();
}
checkscope() // =>"local scope",结果是显然的
对代码做一点改动:
var scope = "global scope"
function checkscope () {
var scope = "local scope"
function f() {
return scope;
}
return f;
}
checkscope()() // =>"local scope",结果有点意外
函数定义时的作用域链在函数执行时依然有效。
function counter () {
var n = 0;
return {
count: function(){
return n++;
},
reset: function(){
return n = 0;
}
}
}
var a = new counter(); //创建了两个独立的作用域链和私有变量
var b = new counter();
console.log(a.count());// =>0
console.log(b.count());// =>0
console.log(a.reset());// =>0
console.log(b.count());// =>1
应用场景
- 实现对象的私有属性存取器
function defineProperty(o, property){
var value = '';
o['set' + property] = function (v) {
value = v;
}
o['get' + property] = function (v) {
return value;
}
}
var obj = {};
defineProperty(obj,'Name')
obj.setName('javascript');
console.log(obj.getName());
- 防抖函数(n秒内只执行一次,如果n秒被再次触发,那么重新计时),把
function debounce (fn, ms) {
let timer = null;
return function (... args) {
if(timer){
clearTimeout(timer);
}
timer = setTimeout(fn.applay(this, args), ms)
}
}
-
模拟块级作用域(for循环)
-
缓存执行结果
var fn=(function(){
var cache={}//将结果缓存到该对象中,
return function(){
var str=JSON.stringify(arguments);
if(cache[str]){//
return cache[str];
}else{//进行计算并返回结果
var sum=0;
for(var i=0;i<arguments.length;i++){
sum+=arguments[i];
}
return cache[str]=sum;
}
}
})() -
柯里化函数式编程
// 柯里化之前
function add(x, y) {
return x + y;
}
add(1, 2) // 3// 柯里化之后
function addX(y) {
return function (x) {
return x + y;
};
}
addX(2)(1) // 3
6.单例模式
练习题目:
function fun(n,o){
console.log(o);
return {
fun:function(m){
return fun(m,n);
}
};
}
var a = fun(0);a.fun(1);a.fun(2);a.fun(3);
var b = fun(0).fun(1).fun(2).fun(3);
var c = fun(0).fun(1);c.fun(2);c.fun(3);
网友评论