js中var let const 区别详解

论坛 期权论坛 期权     
前端从入门到SP   2019-7-13 08:26   3122   0

首先要理解js中作用域的概念
作用域:指的是一个变量的作用范围
1.全局作用域
直接写在script中的js代码,在js中,万物皆对象,都在全局作用域,全局作用域在页面打开时创建,在全局作用域中有一个全局对象window,它代表是一个浏览器的窗口它由浏览器创建可以直接使用,在全局作用域中,创建的对象都可以都可以作为window对象的属性保存,在任何地方都可以调用
2.函数作用域
调用函数时创建函数作用域,函数执行完毕后,函数作用域销毁,每调用一次函数会创建一个新的函数作用域他们之间是相互独立的,函数中可以访问到全局作用域的变量,反之不行。当在函数作用域中操作对象,如果有,则使用,如果没有则向其上一个作用域(不是指的是全局作用域)找,直到找到全局作用域无论在那个作用域,都有变量声明提前现象,在函数中不用var声明的变量都会设置为全局变量,形参相当于在函数作用域里声明变量var定义的变量可被更改,如果不初始化而直接使用也不会报错,var声明的变量会得到提升,其余两个不存在这种情况,即必须先声明再赋值
let定义的变量和var类似,但作用域在当前声明的范围内
const定义的变量只可初始化一次且作用域内不可被更改,使用前必须初始化
1.var的变量提升
js和其他语言一样,都要经历编译和执行阶段。而js在编译阶段的时候,会搜集所有的变量声明并且提前声明变量,而不会改变其他语句的顺序,因此,在编译阶段的时候,第一步就已经执行了,而第二步则是在执行阶段执行到该语句的时候才执行
var即可用于函数外,亦可用于函数内,这就涉及到全局变量与局部变量的问题,
全局变量如何声明:
在函数外声明的变量就是全局变量,反之,在函数内声明的变量就是局部变量,
作用域:全局变量无论在函数内,还是函数外,都可访问到;
局部变量只能在函数内有效,函数外部访问不到该变量及说对应的变量值
经典案例
  1.   
复制代码
  1.         var a = 10;
复制代码
  1. [/code][code]        function change() {
复制代码
  1.             console.log(a);
复制代码
  1.             var a = 7;    //变量提升原因  例子1
复制代码
  1.         }
复制代码
  1.         change()  //输出为undefine
复制代码
  1.         console.log(a);//输出为10
复制代码
  1. [/code][code]
复制代码
  1.         var a = 10;
复制代码
  1.         function change() {
复制代码
  1.             a = 7;  //改变了全局变量a的值
复制代码
  1.         }
复制代码
  1.         change();
复制代码
  1.         console.log(a);//输出为7
复制代码
  1. [/code][code]
复制代码
  1.         var a = 10;
复制代码
  1.         function change() {
复制代码
  1.             var a = 7;  //作用域的原因,a属于函数作用域。
复制代码
  1.         }
复制代码
  1.         change();
复制代码
  1.         console.log(a);//输出为10 输出的a是全局区域中的a,因为局部变量只能在函数内有效,函数外部访问不到该变量及说对应的变量值
复制代码
  1. [/code]let是块级作用域,函数内部使用let定义后,对函数外部无影响
  2. ES6 新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。
  3. [list][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][/list][code]{
复制代码
  1.   let a = 10;
复制代码
  1.   var b = 1;
复制代码
  1. }
复制代码
  1. a // ReferenceError: a is not defined.
复制代码
  1. b // 1
复制代码
  1. 不可以{
复制代码
  1. let a = 1;
复制代码
  1. let = 3;重复定义在一个块级作用域
复制代码
  1. }
复制代码
  1. for循环的计数器,就很合适使用let命令
复制代码
  1. for (let i = 0; i < 10; i++) {
复制代码
  1.   // ...
复制代码
  1. }
复制代码
  1. console.log(i);
复制代码
  1. // ReferenceError: i is not defined
复制代码
  1. 暂时性死区
复制代码
  1. var tmp = 123;
复制代码
  1. if (true) {
复制代码
  1.   tmp = 'abc'; // ReferenceError//下面定义了let tmp 上面只要这种操作就是暂时性死区,为了让我们编码严格 const也是
复制代码
  1.   let tmp;
复制代码
  1. }
复制代码
  1. 为什么用块级作用域?
复制代码
  1. 1.例子1的变量提升,2就是for循环中的i
复制代码
  1. 以下为块级作用域
复制代码
  1. function f1() {
复制代码
  1.   let n = 5;
复制代码
  1.   if (true) {
复制代码
  1.     let n = 10;
复制代码
  1.   }
复制代码
  1.   console.log(n); // 5
复制代码
  1.   如果是var,的话会输出10
复制代码
  1. }
复制代码
  1. [/code]const声明一个只读的常量。一旦声明,常量的值就不能改变。
  2. [list][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][/list][code]对于const来说,只声明不赋值,就会报错。
复制代码
  1. const的作用域与let命令相同:只在声明所在的块级作用域内有效。
复制代码
  1. const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
复制代码
  1. const声明的常量,也与let一样不可重复声明。
复制代码
  1. 本质
复制代码
  1. const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
复制代码
  1. const foo = {};
复制代码
  1. [/code][code]// 为 foo 添加一个属性,可以成功
复制代码
  1. foo.prop = 123;
复制代码
  1. foo.prop // 123
复制代码
  1. [/code][code]// 将 foo 指向另一个对象,就会报错
复制代码
  1. foo = {}; // TypeError: "foo" is read-only
复制代码
[code][/code]

更多精彩文章
js进阶之函数与对象
原生js实现打飞机和静态留言表
js+Canvas实现热力图
js+Canvas实现时钟图,简单易懂
js+vue实现轮播图,大致功能实现
Vue2.0搭建Vue脚手架及ECharts入门,VUE组件中传值实例
玩转github(一)

更多前端资料请关注公众号:前端从入门到SP
扫描二维码关注公众号




分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:30
帖子:6
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP