• 复习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的值
  • 相关阅读:
    xyplorer设置备忘
    如何在CentOS 8上安装Python2 Python3
    为CentOS 8操作系统安装MySQL的方法,以安装MySQL 8为例
    SSH登录服务器报ECDSA host key "ip地址" for has changed and you have requested strict checking
    Linux常用命令大全
    转载:php的几种常用的数据交换格式
    转:GBK编码 VS UTF8编码
    转载:中文在UTF8和GBK编码中的范围
    转:SDL Specification and Description Language 简介
    转:Java中Split函数的用法技巧
  • 原文地址:https://www.cnblogs.com/morongwendao/p/8405370.html
Copyright © 2020-2023  润新知