• var let const 无关键字定义变量


    作用域控制着变量与参数的可见性与生命周期。首先理解两个概念:块级作用域与函数作用域。

    1.全局作用域
    (1) 全局作用域在页面打开时被创建,页面关闭时被销毁
    (2) 编写在script标签中的变量和函数,作用域为全局,在页面的任意位置都可以访问到
    (3) 在全局作用域中有全局对象window,代表一个浏览器窗口,由浏览器创建,可以直接调用
    (4) 全局作用域中声明的变量和函数会作为window对象的属性和方法保存

    1.块级作用域

    任何一对花括号 {} 中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。比如if() {} ,for() {}中的花括号都是块级作用域

    为什么需要块级作用域?

      在ES5中,只有全局作用域和函数作用域,不存在块级作用域,这就会导致如下问题的发生

    • 1)内层变量覆盖外层变量
    • 2)用于循环的计数变量会泄露为全局变量

    2.函数作用域

    很明显是function(){}的形式,定义在函数中的参数和变量在函数外部是不可见的

    调用函数时,函数作用域被创建,函数执行完毕,函数作用域被销毁。每调用一次函数就会创建一个新的函数作用域,他们之间是相互独立的。在函数作用域中可以访问到全局作用域的变量,在函数外无法访问到函数作用域内的变量。在函数作用域中访问变量、函数时,会先在自身作用域中寻找,若没有找到,则会到函数的上一级作用域中寻找,一直到全局作用域

    var是忽视块级作用域的,也就是说在块级作用域中用var定义,在外部是可以访问到变量值得,var只有在函数作用域中声明外部才不能访问。而且var声明的变量会被声明提前,被提升到作用域顶部,并被赋值为undefinded

    const和let是有块级作用域概念的,也就是说在块级作用域中用const或者let定义,外部无法访问变量,且不可以声明提前

    var

    1)可重复定义 

    2) 声明时可以不赋值

    3)js程序在正式执行之前,会将所有var 声明的变量和function声明的函数,预读到所在作用域的顶部,但是对var 声明只是将声明提前,赋值仍然保留在原位置

    4)无法定义块级作用域变量,在块级作用域中定义相当于定义了一个全局变量

    let

    1)可以声明时不赋值

    2)在同一作用域中不可以重复定义(也包括不能和var,const变量名重复)

    3)不会被声明提前(与var有区别)

    4)可以声明块级作用域的变量,块级作用域外无法访问内部变量

    const

    1)当声明时不赋值报错

    2)当试图改变const常量时报错

    3)在同一作用域中重复定义报错

    4)不会被声明提前(与var有区别)

    5)可以声明块级作用域的变量,块级作用域外无法访问内部变量

    本质:const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。
        - 简单数据类型( 数值、字符串、布尔值): 值就保存在变量指向的那个内存地址,因此等同于常量
        - 复合数据类型( 对象和数组) : 变量指向的内存地址,保存的只是一个指向实际数据的指针 , const只能保证这个指针是固定的 至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
    对象冻结:如果希望将一个对象进行冻结,可使用Object.freeze():

    const person = Object.freeze({})

    但上面的冻结方式只是将其对象本身冻结,其对象的属性也应该冻结,我们可以使用如下函数:

    var constantize = (obj) => {
        Object.freeze(obj);
        Object.keys(obj).forEach( (key, i) => {
            if ( typeof obj[key] === 'object' ) {
                constantize( obj[key] );
            }
        });
    };

    无关键字定义变量

    在函数作用域中,不使用变量关键字声明的变量,在赋值时会往上一级作用域寻找已经声明的同名变量,直到全局作用域时还没找到,则会成为window的属性

    小结:建议多使用let,毕竟for中的i一般不想被泄露出来,而且if中定义的变量一般只想在条件成立时才定义,实现这些都需要用let,而且let没有变量被声明提前的困扰,其他两者没有太大区别,所以还是改成用let声明变量吧

  • 相关阅读:
    C++ Primer读书笔记
    谨慎使用多线程中的fork
    C++中多线程与Singleton的那些事儿
    浅谈指针的比较
    条件变量的陷阱与思考
    2014年终总结
    循环队列的一种实现模型
    react-native使用jest、enzyme进行单元测试
    富文本编辑器开发原理
    模拟实现单元测试中的异步测试
  • 原文地址:https://www.cnblogs.com/icctuan/p/12132190.html
Copyright © 2020-2023  润新知