美文网首页
js闭包及作用域/作用域链

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

作者: 小麻烦爱学习 | 来源:发表于2020-01-16 11:10 被阅读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);
    

    相关文章

      网友评论

          本文标题:js闭包及作用域/作用域链

          本文链接:https://www.haomeiwen.com/subject/zmlfzctx.html