美文网首页
作用域和闭包

作用域和闭包

作者: 安好每个你 | 来源:发表于2017-10-26 15:00 被阅读8次
    fn()        //声明内容先执行不会报错
    function fn() {
        //函数声明
    }
    fn1()         //先执行fn1函数会报错
    var fn1 = function() {
        //函数表达式
    }
    

    执行上下文

    范围:一段<script>或者一个函数
    全局(一段<script>):变量定义,函数声明
    函数:变量定义,函数声明,this,arguments

    console.log(a)          //undefined
    var a = 100
    
    fn('zhangsan')          //'zhangsan' 20 
    finction fn(name) {
        age = 20
        console.log(name, age)
        var 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
    

    作为构造函数执行
    作为对象属性执行
    作为普通函数执行
    call apply bind

    \\构造函数
    function Foo(name) {
        this.name = name              //this先赋值成空对象this={}
    }
    var f = new Foo('zhangsan')
    
    \\对象属性
    var obj = {
        name: 'A',
        printName: function() {
            console.log(this.name)
        }
    }
    obj.printName()                 //this === obj
    
    //普通函数
    function fn() {
        console.log(this)
    }
    fn()                                //this == window
    
    //call apply bind
    function fn1(name) {
        alert(name)
        console.log(this)
    }
    fn1.call({x:100}, 'zhangsan')                //this === {x:100}
    bind要用在函数表达式中
    

    作用域

    js没有块级作用域
    只有函数和全局作用域

    //无块级作用域
    console.log(name)
    if (true) {
        var name = 'zhangsan'
    }
    console.log(name)
    
    //函数和全局作用域
    var a = 100
    function fn() {
        var a = 200
        console.log('fn', a)
    }
    console.log('global', a)
    fn()
    

    作用域链

    var a = 100
    function fn() {
        var b = 200
        // 当前作用域没有定义的变量,即“自由变量”
        //当前作用域没有定义的,要去父级作用域寻找,函数在哪定义,在哪找父级作用域
        console.log(a)
        console.log(b)
    }
    fn()
    

    作用域链就是自由变量不断的向父级作用域寻找

    var a = 100
    function F1() {
        var b = 200
        function F2() {
            var c = 300
            console.log(a)
            console.log(b)
            console.log(c)
        }
        F2()
    }
    F1()
    

    闭包

    function F1() {
        var a = 100
        // 返回一个函数(函数作为返回值)
        return function () {
            console.log(a)        //自由变量,父作用域寻找
        }
    }
    //f1得到一个函数
    var f1 = F1()
    var a = 200
    f1()         //100
    

    闭包使用场景
    1.函数作为返回值(上一个demo)
    2.函数作为参数传递

    function F1() {
        var a = 100
        // 返回一个函数(函数作为返回值)
        return function () {
            console.log(a)        //自由变量,父作用域寻找
        }
    }
    var f1 = F1()
    function F2 (fn) {
        var a = 200
        fn()
    }
    F2(f1)        //100
    

    说一下对变量提升的理解

    变量定义
    函数声明(注意和函数表达式的区别)

    说明this几种不同的应用场景

    作为构造函数执行
    作为对象属性执行
    作为普通函数执行
    call apply bind

    创建10个<a>标签,点击的时候弹出来对应的序号

    //正确方法
    var i
    for (i = 0; i < 10; i++) {
        //自执行函数,就是不用调用,只要定义完成,立即执行的函数
        (function(i) {
            var a = document.createElement('a')
            a.innerHTML = i + '<br>'
            a.addEventListener('click', function(e){
                e.preventDefault()
                alert(i)
            })
            document.body.appendChild(a)
        })(i)      //传入参数
    }
    
    //错误方法
    var i, a
    for (i=0; i<10; i++) {
        a = document.createElement('a')
        a.innerHTML = i + '<br>'
        a.addEventListener('click', function(e) {
            e.preventDefault()
            alert(i)                           //自由变量,要去父作用域获取值
        })
        document.body.appendChild(a)
    }
    无论点击哪个数字出来的都是10
    

    如何理解作用域

    自由变量
    作用域链,即自由变量的查找
    闭包的两个场景

    实际开发中闭包的应用

    //闭包实际应用中主要用于封装变量,收敛权限
    function isFristLoad() {
        //_表示私有变量
        var _list = []
        return function (id) {
            if (_list.indexOf(id) >= 0) {
                return false
            } else {
                _list.push(id)
                return true
            }
        }
    }
    
    //使用
    var firstLoad = isFristLoad()
    firstLoad(10)    //true
    firstLoad(10)    //false
    firstLoad(20)    //true
    //你在 isFirstLoad 函数外面,根本不可能修改 掉 _list 的值
    

    相关文章

      网友评论

          本文标题:作用域和闭包

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