ES6的let和const,一篇文章就够了

1 篇文章 0 订阅
1 篇文章 0 订阅

ES6系列之let和const

let声明符

ES6 新增的let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

注意

let 声明变量

  1. 不会进行变量提升 无法在声明之前使用let声明的变量

  2. let声明的变量不容许重复声明 预解析阶段会对let声明的变量锁定 所有其他在同一个域下的声明都会报错

  3. let会开启块级作用域

基础特性
 if(true){
   let a = 'let';
   var b = 'var';
 }
 ​
 console.log(b); //var
 console.log(a); //Uncaught ReferenceError: a is not defined---------------------------------------------------------//使用let,声明的变量仅在块级作用域内({ })有效,最后输出的是 6。
 for(let i = 0; i < 10; i++){
     
 }
 console.log(i); //Uncaught ReferenceError: i is not defined

上面代码在代码块之中,分别用letvar声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。

 // 在循环体表达式中let声明迭代变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量
 var a = [];
 for (let i = 0; i < 10; i++) {
   a.push(function () {
     console.log(i);
   });
 }
 a[5](); // 5
 // 在循环体表达式中let声明 和循环体中let 声明同名变量是不冲突的 设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。相当于每次循环{}内部都会单独开一个局部作用域
 for (let i = 0; i < 3; i++) {
   let i = 'abc';
   console.log(i);
 }
不进行变量提升

var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined

let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。 这一点需要特殊注意

 // var 的情况
 console.log(num); // 输出undefined
 var num = 2;-------------------------
     
 // let 的情况
 console.log(age); // 报错ReferenceError
 let age = 16;
致死域(暂时性死区)

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

 //正常调用
 let num = 10;
 if (true) {
     console.log(num); //10
 }------------------//if { }内部let为独立局部作用域 访问为 20
 let num = 10;
 if (true) {
     let num = 20;
     console.log(num); //20
 }------------------
 ​
 ​
 //发生致死 因为fn局部作用域中有let声明num 所以在作用域内 不能先调用再使用let声明。
 let num = 10;
 function fn() {
     console.log(num); //Uncaught ReferenceError: Cannot access 'num' before initialization
     let num = 20;
 }
 fn();
 ​
 ​
 ------------------//typeof操作影响typeof num;
 let num; //Uncaught ReferenceError: Cannot access 'num' before initialization------------------let num = 10;
 if (true) {
   var num = 20;
   console.log(num); //报错 Identifier 'num' has already been declared
 }var num;
 let num = 10;
 if (true) {
   num = 20;
   console.log(num); 报错 Identifier 'num' has already been declared
 }-------------------
 //如果在某一个作用域中有let声明某一个变量 那在这个作用域中就不能再let声明之前使用这个变量

 let num = 10; //全局作用域
 function fn() {//
   console.log(num); //Uncaught ReferenceError: Cannot access 'num' before initialization
   let num = 20; //局部作用域
 }
 fn();-------------------
 function fn() {
    console.log(num);
    num = 20; //局部作用域
  }
  fn();
  let num = 10; //全局作用域   报错 num is not defined  
-------------------
 //作用域链: 外部作用域无法访问内部作用域的私有变量  作用域访问只能由内之外 由下至上
 function fn() {
   var x = 20;
 }
 fn();
 console.log(x);// 报错  x is not defined/*
   1.  for if 没有独立的局部作用域
   2.  i 是全局变量(当前案例环境下) i指代内存地址 [内存地址:[值]]
   3. 每一个地址里面的值在每个时刻都只可能是一个唯一的状态(值)
   4. 内部push的fn fn内部作用域引用了外部作用域的变量 i
   5. 当arr[1]() 执行的时候 解析函数内部变量指向 发现i指向全局 i 对应地址当前存储的值是 5
   6. 循环中每次循环的时候 立刻调用一个IIFE匿名函数 并将i的值
   7. 左查询(赋值) 右查询(调用) 作为实参传递的时候是右查询
   8. IIFE (结构体表达式)(调用前面的结构体 传递实参)
     fn()
   9. 块级别作用域
 */
    
 var arr = [];
 var i = 0;
 for (; i < 5; i++) {
   (function (i) {
     var i = 0; //i=1; i=2
     arr.push(function () {
       console.log(i);
     })
   })(i);
 }
 console.log(i);
 // i
 arr[1](); //5
 ​
 ​
 var w = 10;
 function fn(w) {
   console.log(w); //30
   // var w;
   //函数的形参会作为函数的局部变量隐式声明
   w = 20;
   // console.log(w); //20
 }
 fn(w); //变量作为实参传递的时候 是将当前时刻变量的值传入fn(调用w);//右查询 w  左查询
​
 x = 300; //x为左查询 (赋值)
​
 y = x; //x为右查询 y为左查询

当程序的控制流程在新的作用域(module function 或 block 作用域)进行实例化时,在此作用域中用let/const声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在这运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区。

es6规定 let/const 会使区域形成封闭的作用域 若在声明之前使用变量就会发生错误, 在代码块内使用let命令声明变量之前 该变量都无法使用,称为“暂时性死区”(temporal dead zone,简称 TDZ)。总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。使用let 确保先 声明 再 使用 变量 不要混用let和var在同一个作用域链上 避免死区

无法重复声明

let不允许在相同作用域内,重复声明同一个变量。

 //发生致死 因为var会变量提升。
 let num = 10;
 if (true) {
     var num = 20; //Uncaught SyntaxError: Identifier 'num' has already been declared
     console.log(num);
 }
块作用域 (block scope)

在ES5中,只全局作用域和函数作用域。这会导致函数作用域覆盖了全局作用域;亦或者循环中的变量泄露为全局变量。

EcmaScript 6引入了块级作用域(block scope),块级作用域只能在块中被访问,以下两种情况可以创建块级作用域的变量。

  • 在函数中
  • 在被{}包裹的块中
 {
     var x = 10;
 }
 console.log(x); //10------------------{
     let x = 10;
 }
 console.log(x);//x is not defined------------------//函数有两个代码块,都声明了变量num,运行后输出 3。这表示外层代码块不受内层代码块的影响。如果两次都使用var定义变量num,最后输出的值才是 6。
 function fn() {
   let num = 3;
   if (true) {
     let num = 6;
   }
   console.log(num); // 3
 }
 fn();-----------------------
 //作用域链: 外部作用域无法访问内部作用域的私有变量  作用域访问只能由内之外 由下至上
 function fn() {
   var x = 20;
 }
 fn();
 console.log(x);// 报错  x is not defined
块作用域下的函数声明

ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。

ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。

function a() {
     console.log('我是全局作用域内声明的函数a');
 }
 
 (function () {
     if (false) {
         function a() {
             console.log('我是块级作用域内声明的函数a');
         }
     }
     a();        //报错  a is not a function
 })();----------------------
 ​
 ​
 function a() {
     console.log('我是全局作用域内声明的函数a');
 }
 (function () {
     var a;
     if (false) {
         a = function () {
             console.log('我是块级作用域内声明的函数a');
         }
     }
     a();        //报错  a is not a function
 })();------------------
 //用{}不会变量冲突
 {
       let oSlider = document.querySelector('.slider');
       let index = 0;
       oSlider.onmouseover = function () {
         this.innerHTML = index++;
       }
 }{
     let oSlider = document.querySelector('.other-slider');
     let index = 0;
     oSlider.onmouseover = function () {
         this.innerHTML = index++;
     }
 }

为了减轻因此产生的不兼容问题,ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式

  • 允许在块级作用域内声明函数。
  • 函数声明类似于var,即会提升到全局作用域或函数作用域的头部。
  • 同时,函数声明还会提升到所在的块级作用域的头部。

const声明符

const声明一个只读的常量。一旦声明,常量的值就不能改变。 const与let在 块作用域 重复声明 致死域的问题上是一致的 const的作用域与let命令相同:只在声明所在的块级作用域内有效。

 const DATA = '我是常量 不能改变哦';
 DATA //  '我是常量 不能改变哦'DATA = '改一个试试看';
 // TypeError: Assignment to constant variable.

const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

const 声明常量

常量:

是一个固定值 不会改变 不能改变 是客观事实提供的固定值 PI E lg(10) sin(0)

编程中的常量: 保证变量值的安全性

const 只读变量(客观值 固定值)

  1. const 声明的变量值 不容许修改

  2. 拥有let所有的特性

  3. 变量不会提升

  4. 不容许先调用后声明

  5. 不容许重复声明

  6. 能够开启块作用域

  7. const声明的变量声明时必须赋值

  8. const的值如果是引用类型 值的属性可以修改

  9. 常量变量名称 建议 全大写 _链接多个单词

声明时必须赋值
 const X;
 //Uncaught SyntaxError: Missing initializer in const declaration
值为对象
 const KEY_MAP = {
     a:1,
     b:2
 }KEY_MAP['a'] = 2; //不报错-----------
     
 const ARRAY = [];
 ARRAY.push('something'); // 可执行
 ARRAY.length = 0;    // 可执行
 ARRAY = ['something'];    // 报错//const的值如果是引用类型 值的属性可以修改
 document.onscroll = function (e) {
   const scrollData = {
     top: document.documentElement.scrollTop,
     left: document.documentElement.scrollLeft,
 }
   console.log(scrollData.top);
   scrollData.top = 10;              //可修改
   console.log(scrollData.top);
 }
喜欢本文就点个赞吧,我们一起加油

658308afed3467edf02e542d8a542b9.jpg

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一篇关于JavaScript经验案例的文章。 作为一名前端开发工程师,我在工作中使用JavaScript的时间非常长。在这个过程中,我积累了许多有关JavaScript的经验,今天我想分享一些关于JavaScript的技巧和经验,希望对大家有所帮助。 1. 使用模块化编程 在编写JavaScript代码时,使用模块化编程可以使代码更加清晰和可维护。模块化编程可以将代码分成多个模块,每个模块都有自己的作用域和变量,这样可以避免变量污染和命名冲突。使用模块化编程还可以方便地重用代码。 例如,我在一个项目中使用了RequireJS框架,将代码分成了多个模块。每个模块都有自己的依赖关系,这样可以方便地管理代码依赖性。使用RequireJS还可以实现异步加载,提高网页的加载速度。 2. 使用ES6语法 ES6JavaScript的一个新版本,它引入了许多新的语法和功能,使得JavaScript更加现代化和强大。在编写JavaScript代码时,使用ES6语法可以使代码更加简洁和易读。例如,使用letconst关键字可以避免变量污染和命名冲突,使用箭头函数可以使代码更加简洁,使用模板字符串可以方便地拼接字符串。 例如,我在一个项目中使用了ES6的模板字符串功能,将HTML模板和JavaScript代码分离。这样可以使代码更加清晰,易于维护。 3. 使用jQuery框架 jQuery是一个非常流行的JavaScript框架,它提供了许多实用的函数和工具,可以方便地操作DOM元素,处理事件,以及实现动画效果。在编写JavaScript代码时,使用jQuery可以大大提高开发效率和代码的可读性。使用jQuery还可以避免浏览器兼容性问题。 例如,我在一个项目中使用了jQuery框架,通过选择器和DOM操作函数,实现了网页上的动画效果。使用jQuery可以大大简化代码,提高开发效率。 4. 使用Ajax技术 在Web开发中,Ajax技术可以使网站更加动态和交互。使用Ajax可以在不刷新网页的情况下向服务器发送请求,获取数据并更新网页内容。在JavaScript中,可以使用XMLHttpRequest对象或jQuery的$.ajax函数来实现Ajax请求。 例如,我在一个项目中使用了Ajax技术,实现了网站的搜索功能。用户输入关键词后,页面不会刷新,而是通过Ajax请求向服务器发送请求,获取搜索结果并更新网页内容。这样可以提高用户体验,使网站更加动态和交互。 5. 使用调试工具 在编写JavaScript代码时,调试是一个非常重要的环节。使用调试工具可以帮助我们快速发现和修复代码错误。浏览器自带的开发者工具是一个非常实用的调试工具,可以帮助我们查看JavaScript代码的执行过程,检查DOM元素和网络请求等信息。 例如,我在一个项目中使用了Chrome浏览器的开发者工具,检查JavaScript代码的执行过程,查看调用栈和变量值,以及检查DOM元素和网络请求等信息。使用调试工具可以帮助我们快速发现和修复代码错误,提高开发效率。 总结 在JavaScript开发中,使用模块化编程、ES6语法、jQuery框架、Ajax技术和调试工具等技术和工具,可以使代码更加清晰、易读和可维护,提高开发效率和网站性能。当然,这些只是JavaScript开发中的一部分技巧和经验,还有许多需要我们不断学习和掌握。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值