zoukankan      html  css  js  c++  java
  • js作用域

    1.什么是作用域?

    作用域就是变量与函数的可访问范围,即作用域控制着函数与变量的可见性和生命周期

    1.全局作用域

    任何地方都能访问到的对象拥有全局作用域

    1.1.函数外面定义的变量拥有全局作用域,全局变量拥有全局作用域,网页中所有脚本和函数均可使用。全局变量在页面关闭后销毁

    var n = 2;
    function fn(){
        var a = 1;
        returrn a;  
    }
    
    console.log(fn());   //1
    console.log(n);  // 2
    console.log(a);   //报错error

    1.2.未定义直接赋值的变量自动声明为全局变量拥有全局作用域

    var n = 2;
    function fn(){
        a = 1;
        returrn a;  
    }
    
    console.log(fn());   //1
    console.log(n);  // 2
    console.log(a);   //1

    1.3.window对象的属性拥有全局作用域

    HTML中,全局变量是window对象,所有数据变量都属于window对象

    //此处可使用 window.carName
     
    function myFunction() {
        carName = "Volvo";
    }

    2.局部作用域

    局部作用域一般只在固定的代码片段内能访问到,最常见的例如函数内部,所以也称为函数作用域

    变量在函数内声明,变量为局部作用域

    局部变量:只能在函数内访问

    // 此处不能调用 carName 变量
    function myFunction() {
        var carName = "Volvo";
        // 函数内可调用 carName 变量
    }

    因局部变量只作用于函数内,所以不同的函数内可以使用相同名称的变量名

    局部变量在函数开始执行时创建,函数执行完成后局部变量会自动销毁

    3.ES6的块级作用域

    ES5只有全局作用域和函数作用域,没有块级作用域,会带来以下问题

    3.1.变量提升导致内层变量可能会覆盖外层变量

    var  i = 5;
    function func(){
        console.log(i);
        if(true){
              var i = 6;       
        }
    }
    func();   //undefined

    3.2.用来计数的循环变量泄露为全局变量

    for(var i = 0;i<10;i++){
       console.log(i)
    }
    console.log(i);  //10

    ES6引入了块级作用域,明确允许在块级作用域中申明函数,let和const命令都涉及块级作用域

    块级作用域允许声明函数只在使用大括号的情况下成立,如果未使用大括号报错

    if (true) {
    
    function func1() {} // 不报错
    
    }
    
    if (true)
    
    function func2() {} // 报错

    作用域链

    当声明一个函数时,局部作用域一级一级向上包起来,就是作用域链

    1.当执行函数时,总是先从函数内部寻找局部变量

    2.如果内部找不到(函数的局部作用域没有),则会像创建函数的作用域(声明函数的作用域)寻找,依次向上

    var a = 1;
    function fn(){
        var a = 10;
        function fn1(){
            var a = 20;
            console.log(a);  //20 
         }
        function fn2(){
           console.log(a);  //10
        }
        fn1();
        fn2();
    }      
    fn();
    console.log(a);  //1  

    当执行fn1()时,创建函数fn1的执行环境,并将该对象置于链表开头,然后将fn的调用对象放在第二位,最后是全局对象,作用域链的链表结构是fn1>fn>window,从链表的开头寻找变量a,即从fn1函数内部找变量a,找到了结果是20.

    同样,当执行fn2()时,创建函数fn2的执行环境,并将该对象置于链表开头,然后将fn的调用对象放在第二位,最后是全局对象,作用域链的链表结构是fn2>fn>window,从链表的开头寻找变量a,即从fn2函数内部找变量a,找不到,于是从fn内部找变量a,找到了结果是10

    最后再最外层打印变量a,直接从变量a的作用域即全局作用域内寻找,结果为1

    4.闭包

    简单来说,闭包就是函数外部能读取到函数内部的变量

    优点:闭包可以形成独立的空间,永久的保存局部变量

    缺点:保存中间值的状态缺点是造成内存泄漏,因为闭包中的局部变量永远不会被回收

    function f1(){
         var n = 999;
         nAdd = function(){
           n += 1;
        }
        function f2(){
               console.log(n)
        }
        return f2;
    }  
    
    var result = f1();
    result();  //999
    nAdd();  //执行 n+=1;
    result();  //1000  
  • 相关阅读:
    HDU 1284 思维上的水题
    Buy Tickets POJ
    K-th Number Poj
    主席树入门+博客推荐
    Greg and Array CodeForces 296C 差分数组
    三连击 P1008 洛谷 python写法
    Lost Cows POJ 2182 思维+巧法
    Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论
    Can you answer these queries? HDU 4027 线段树
    敌兵布阵 HDU 1166 线段树
  • 原文地址:https://www.cnblogs.com/woshidouzia/p/10912195.html
Copyright © 2011-2022 走看看