zoukankan      html  css  js  c++  java
  • 复习3----作用域和闭包

     
    题目
    1.说一下对变量提升的理解
    2.说明this几种不同的使用场景
    3.创建10个<a>标签,点击时弹出对应序号
    4.如何理解作用域
    5.实际开发中闭包的应用
     
    知识点#####
    • 执行上下文
     
    范围:一段<script>或者一个函数 或者eval代码
    全局:变量定义、函数声明 (提前拿出来)                    针对一段<script>
    函数:变量定义、函数声明、this、arguments  (提前拿出来)                    针对一个函数
     eval不常用,也不推荐大家用。
     
    在一段js代码拿过来真正一句一句运行之前,浏览器已经做了一些“准备工作”,在“准备工作”中完成了哪些工作:
    1.变量、函数表达式——变量声明,默认赋值为undefined;
    2.this——赋值;
    3.函数声明——赋值;
    这三种数据的准备情况我们称之为“执行上下文”或者“执行上下文环境”。
     
     
    ps:注意函数声明和函数表达式的区别
    //函数声明
    function fn(){
        //.....
    }
     
    //函数表达式
    var fn1=function(){
        //.....
    }
    //全局console.log(a); //undefined
    var a=100
     
    fn('zhangsan') //zhangsan 20
    function fn(name){
        //函数
        console.log(this); //Window
        console.log(arguments); //"zhangsan"
        age=20
        console.log(name,age);
        var age   //age会提前
    }
    • this
     
    this要在执行时才确认值,定义时无法确认
    var a={
        name:'A',
        fn:function(){
            console.log(this.name);
        }
    }
    a.fn() //this===a
    a.fn.call({name:'B'}) //this==={name:'B'}
    var fn1=a.fn
    fn1() //this===Window
    • - 作用域
    js没有块级作用域
    if(true){
        var name='zhangsan'
    }
    console.log(name); //zhangsan

    只有函数和全局作用域

    var a=100
    function fn(){
        var a=200
        console.log('fn',a)
    }
    console.log('global',a)  //global 100
    fn() //fn 200
    •  作用域链
    自由变量
    var a=100
    function fn(){    
        var b=200    
        console.log(a) //当前作用域没定义的变量,即'自由变量'    
        console.log(b)
    }
    fn() //100 200

    调用在当前作用域不存在的变量,便会向父级作用域查找。需要注意的是,父级作用域是函数定义时产生的,并非函数调用时。

    var a=100
    function F1(){
        var b=200
        function F2(){
            var c=300
            console.log(a) //a是自由变量,在F2中未找到便向父级作用域F1查找,仍未找到,继续向上查找,在Window中找到
            console.log(b) //b是自由变量
            console.log(c)
        }
        F2()
    }
    F1() //100 200 300
    • - 闭包
    使用场景,函数作为返回值;函数作为参数传递
    //闭包的使用场景:函数作为返回值
    function F1(){
        var a=100
        //返回一个函数
        return function(){
            console.log(a) //自由变量,父作用域查找,仍未找到,继续向上查找,在Window中找到
        }
    }
    //f1得到一个函数
    var f1=F1()
    var a=200
    f1()  //100   
    //闭包的使用场景:函数作为参数传递
    function F1(){
        var a=100
        return function(){
            console.log(a) //自由变量,父作用域查找
        }
    }
    var f1=F1()
    function F2(fn){
        var a=200
        fn()
    }
    F2(f1) //100
     
    #####解题#####
    **1.说一下对变量提升的理解**
    执行上下文的知识:http://www.jianshu.com/p/a6d37c77e8db
    在<script>或函数中,各个变量、函数的声明与定义会被提前
     
    **2.说明this几种不同的使用场景**
    this的几种执行情况:
    • 作为构造函数执行
    • 作为对象属性执行
    • 作为普通函数执行
    • call apply bind
    //构造函数
    function Foo(name){
        this.name=name
    }
    var f=new Foo('zhangsan')
    //对象属性
    var obj={
        name:'zhangsan',
        printName:function(){
            console.log(this.name)
        }
    }
    obj.printName()
    //普通函数
    function fn(){
        console.log(this);
    }
    fn()    //window
    //call apply bind
    function fn1(name,age){
        alert(name)
        console.log(this)    
    }
    fn1.call({x:100},'zhangsan',20)    //({x:100}
    //apply
    fn1.apply({x:100},['zhangsan',20])    //({x:100}
    //call, apply方法区别是,从第二个参数起, call方法参数将依次传递给借用的方法作参数, 而apply直接将这些参数放到一个数组中再传递
    //bind
    var fn2=function (name,age){ //bind在函数声明的形式后不可用,必须是函数表达式
        alert(name)
        console.log(this)
    }.bind({y:200})
    fn2('zhangsan',20)   //{y: 200}
    **3.创建10个```<a>```标签,点击时弹出对应序号**
    //错误的写法
        var i,a;
        for(i=0;i<10;i++){
    //除了click函数内部,都为全局作用域,会被覆盖。因此最终 i 的值为10
    //全局作用域
            a = document.createElement('a');
            a.innerHTML = i+'</br>' ;
            a.addEventListener('click',function(e){
                e.preventDefault();
                alert(i);  //i为自由变量,向上去父作用域查找时,值已经变成10. 因为click事件执行时,其它部分早已执行完毕。
            })        
            document.body.appendChild(a);
        }
        
    //正确的写法
    var i
    for(i=0;i<10;i++){
    //多包了一层,除了click函数,其它变量的作用于都变成了函数作用域,而不是全局作用域,因此不会被覆盖。相当于创建了10个函数
        (function(i){      
       //函数作用域
            var a=document.createElement('a')
            a.innerHTML=i
            a.addEventListener('click',function(e){
                e.preventDefault()
                alert(i)   //i为自由变量,向上去父作用域查找,就找到调用时的i值 (加粗处)
            })
            document.body.appendChild(a)
        })(i)
    }
     
    **4.如何理解作用域**
    回答要点:
    自由变量
    作用域链,即自由变量的查找
    闭包的两个场景
     
    **5.实际开发中闭包的应用**
    //闭包实际应用中主要用于封装变量,收敛权限
    function isFirstLoad(){
        var _list=[]
        return function(id){
            if(_list.indexOf(id)>=0){
                return false
            }else {
                _list.push(id)
                return true
            }
        }
    }
    //使用
    var firstLoad=isFirstLoad()9
    firstLoad(10) //true
    firstLoad(10) //false
    firstLoad(20) //true
    //在isFirstLoad函数外,无法修改_list的值
  • 相关阅读:
    Linkerd 2.10(Step by Step)—将 GitOps 与 Linkerd 和 Argo CD 结合使用
    Linkerd 2.10(Step by Step)—多集群通信
    Linkerd 2.10(Step by Step)—使用 Kustomize 自定义 Linkerd 的配置
    Linkerd 2.10(Step by Step)—控制平面调试端点
    Linkerd 2.10(Step by Step)—配置超时
    Linkerd 2.10(Step by Step)—配置重试
    Linkerd 2.10(Step by Step)—配置代理并发
    本地正常运行,线上环境诡异异常原因集合
    Need to invoke method 'xxx' declared on target class 'yyy', but not found in any interface(s) of the exposed proxy type
    alpine 安装常用命令
  • 原文地址:https://www.cnblogs.com/morongwendao/p/8405370.html
Copyright © 2011-2022 走看看