js闭包及作用域/作用域链

2020-01-16  本文已影响0人  小麻烦爱学习

闭包的基础是作用域即作用域链

作用域

作用域是指程序源代码中定义这个变量的区域.全局变量拥有全局作用域,在程序中始终是有定义的.局部变量有局部作用域,在函数体内及所嵌套的函数内是有定义的.函数的参数是局部变量,它的作用域在函数体内

作用域链

作用域链是一个对象列表或者链表,这组对象定义了一段码的作用域中的变量.
当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

应用场景
  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());
  1. 防抖函数(n秒内只执行一次,如果n秒被再次触发,那么重新计时),把
function debounce (fn, ms) {
let timer = null;
return function (... args) {
    if(timer){
        clearTimeout(timer);
    }
    timer = setTimeout(fn.applay(this, args), ms)
}
}
  1. 模拟块级作用域(for循环)

  2. 缓存执行结果
    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;
    }
    }
    })()

  3. 柯里化函数式编程
    // 柯里化之前
    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);
上一篇下一篇

猜你喜欢

热点阅读