zoukankan      html  css  js  c++  java
  • javascript 之闭包、作用域链

    执行环境与作用域

    执行环境

    执行环境都有一个关联的变量对象,环境中定义的变量和函数都是这个对象的属性和方法。

    1. 全局执行环境——window对象(web浏览器中)
    2. 局部(函数)执行环境

    全局变量对象始终存在,而局部变量对象只在函数执行过程中存在。

    作用域

    分为全局和局部作用域
    ES6有了块级作用域。

    作用域链

    当在一个环境中执行时,会创建变量对象的作用域链,作用域链保存在函数的内部属性 [[scope]] 中,保证对执行环境有权访问的变量和函数进行有序访问。

    1. 作用域链前端:当前执行环境的变量对象->包含环境的变量对象->下一层包含环境的变量对象......->全局环境变量对象

    2. 标识符解析时:从作用域链前端一级一级的搜索,向后回溯,没有找到就报错。

    作用域链本质上是一个指针列表,指针指向变量对象。

    Note:
    函数环境中,活动对象为变量对象,初始仅包含arguments对象
    延长作用域链: catch 和 with 语句

    闭包

    闭包就是在一个函数内部可以访问这个函数作用域中变量的【匿名函数】。

    function animals(name){
        return function(){
            console.log(name);
        };
    }
    var a = animals("cat");
    a();    //cat
    

    内部的匿名函数的作用域链包含了自己、外部函数变量对象和全局变量对象,即使外部函数运行结束,外部函数的作用域链销毁,其外部函数变量对象仍被匿名函数作用域链所引用,所以外部函数变量对象一直在内存里,在这个匿名函数销毁时,才会销毁它的作用域链所引用的变量对象。

    闭包一些问题

    1. 闭包占用内存
    2. 闭包保存整个变量对象,使用闭包是引用到的都是同一个变量
    3. 闭包的 this 一般指向 window
    4. 内存泄漏:如果闭包中保存了HTML元素,那这个元素将无法被销毁

    模仿块级作用域

    function test(){
        for(var i=0; i< 10; i++){
            console.log(i);
        }
        console.log(i); //在这里还可以访问到 i
    }
    

    模仿块级作用域的语法示例:

    function test(){
        (function(){
            /*块级作用域*/
            for(var i; ...){...}
        })();
        console.log(i); //报错~
    }
    

    常用在全局作用域添加函数,避免全局作用域的变量和函数过多。

    私有变量

    用在构造函数上,为自定义类型创建私有变量、私有函数和特权方法

    //
    function Person(name){  //name和age是私有变量
        var age = 10;
        function myAge(){  //私有函数
            return age;
        }
        this.getAge = function(){
            return myAge(); //用特权方法访问私有函数和属性
        }
        this.getName = function(){  //特权方法
            return name;
        };
        this.setName = function(newName){   
            name = newName;
        };
    }
    

    //静态私有变量

    (function(){
        var name = "";
        Person = function(value){
            name = value;
        };
        Person.prototype.getName = function(){
            return name;
        };
        Person.prototype.setName = function(value){
            name = value;
        };
    })();
    var p1 = new Person("Sam");
    console.log(p1.getName());      //Sam
    var p2 = new Person("Ben");
    console.log(p2.getName());      //Ben
    console.log(p1.getName());      //Ben
    

    模块模式

    var add = (function(){
        var count = 0;
        return {    //返回一个对象,定义公共接口访问私有变量和函数
            increase: function(){  return count += 1; },
            decrease: function(){   return count -= 1; },
            value: function(){  return count; }
        };
    })();
    add.increase(); //
    console.log(add.value());
    
  • 相关阅读:
    机器学习入门-文本数据-使用聚类增加文本的标签属性
    机器学习入门-文本特征-使用LDA主题模型构造标签 1.LatentDirichletAllocation(LDA用于构建主题模型) 2.LDA.components(输出各个词向量的权重值)
    机器学习入门-文本特征-word2vec词向量模型 1.word2vec(进行word2vec映射编码)2.model.wv['sky']输出这个词的向量映射 3.model.wv.index2vec(输出经过映射的词名称)
    机器学习入门-数值特征-对数据进行log变化
    python中datetime.strptime(),strftime()的应用
    css中的','、'>'、'+'、'~'
    js中const,var,let区别
    css的#和.的区别
    js实现拖放
    [Usaco2005]Part Acquisition
  • 原文地址:https://www.cnblogs.com/qiuqiubai/p/12549670.html
Copyright © 2011-2022 走看看