ES6入门 (一)

let 和 const 命令

  • 定义:let 和 const 都是ES6 当中声明变量的关键字

let

定义

let 用法与var 相似

注意事项

块级作用域

我们使用let 会创建一个块级作用域,这个变量只能在这个块级作用域当中使用。那么问题来了,什么是块级作用域呢?在我们学习js的时候相信大家都知道什么是 局部作用域 什么是 全局作用域 。下面我们例子说明一下

<script>
let a = 5; //当我们在全局范围内声明一个变量的时候,这个变量的块级作用域就是全局作用域
function fn1(){
let b = 10 //当我们在局部范围内声明一个变量,他的块级作用域就是局部作用域
}
</script>
  1. ES5当中 内存变量可能会覆盖外层变量
var a = 'abc';

function f() {
// 函数内部变量提升 相当于 var a 的声明
console.log(a);
if(false) {
var a = 'hello,world'
}
}
f() // undefined

上面代码的原意是,if代码块的外部使用外层的tmp变量,内部使用内层的tmp变量。但是,函数f执行后,输出结果为undefined,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。

  1. 用来计数的循环变量泄露成全局变量
var s = 'hello';
for(var i=0;i<s.length;i++){
console.log(s[i])
}
console.log(i) //5
  1. ES5中 函数只能在顶层的作用域和函数作用域之中声明,不能在块级作用域当中声明。而ES6当中允许在块级作用域之中声明函数。但是函数声明语句的行为类似于 let,在块级作用域之外不可引用
不存在变量提升

如果你已经学过 js 并且有一定的js 基础 那么你对 变量提升 一定不陌生。我们都知道如果按正常逻辑,我们必须声明一个变量,然后才应该可以使用他,而变量提升就可以让我们在声明变量之前就使用这个变量(只是不会报错)

变量提升简单来说:就是在js 代码解析的过程当中 我们会把所有的声明的变量提升到这个变量所在作用域的第一行,也就是说我们在给变量赋值之前使用变量的时候不会报错,因为变量提升让变量的声明体现到了代码解析的最前面。

而我们使用let 声明变量的时候,不存在变量提升。也就是说我们在声明这个变量之前不可以使用这个变量否则就会报错

// 变量提升 相当于 var a 提前声明了一个变量 只有经历赋值操作才可以有值
console.log(a) // undefined
var a = 2
console.log(a) // 2 console.log(b) // 报错
let b = 2
console.log(b) // 2
let的特点就是存在暂时性死区

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

var a = 10;
if (true) {
a = 5; // ReferenceError
let a;
}

在这个代码中, 存在一个全变量 a , 但是在 if 块级作用域内又声明了一个局部变量a,导致局部变量a被绑定在这个块级作用域,所以在let声明变量前,使用这个局部变量都会报错。

ES6 明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)

if(true) {
a = 'abc'; // ReferenceError
console.log(a) // ReferenceError let a ; //遇到了变量的声明 暂时性死区结束
console.log(a) //已经遇到了变量的声明,这个时候打印他 a的值是 undefined
a = 123;
console.log(a) // 结果 123
}
特殊情况的暂时性死区 之 ES6函数存在默认值情况
function fn1(x=y,y=2) {
return [x,y]
}
fn1() //报错

如果你是初次介绍es6 我可以简单给你先介绍一下es6中函数存在默认值的情况。函数的默认值呢,是在我们使用函数并且没有给函数传递实参的时候,这时他的参数的值就等于我们给这个参数设置的默认值

在上述代码中 参数x默认值等于另一个参数 y 但是在这个时候 y 还没有声明,属于 暂时性死区。

function fn1(x=2,y=5) {
return [x,y]
}
fn1() // //[2,5] 因为我们没有给这个函数传递实参 所以参数的默认值就起了作用 fn1(3) // [3,5] fn1(3,4) //[3,4]

默认参数的作用域

一旦设置了参数的默认值,函数进行声明初始化的时候,参数会形成一个单独的作用域。等到初始化结束,这个作用域就会消失 。

var x = 1;

function f(x,y=x) {
console.log(y)
} f(2) // 2

在上述代码当中,参数y的默认值等于变量x。调用这个函数的时候,参数形成了一个单独的作用域 ,在这个作用域里面,函数的一个参数指向的是调用这个函数传递的实参2

 let x = 2
function f1(y=x){
let x = 3;
console.log(y)
}
f1() // 2

在上述代码中同样涉及到一个高级概念 作用域链。与上面例子一样,调用这个函数的时候y=x 形成了一个单独的作用域他是局部作用域,因为在这里x的值不存在,所以根据作用域链,他会向上一层作用域寻找x直到找到他 所以这个例子中 参数y的默认值x 是全局作用域当中声明的变量x

不允许重复声明变量
function fn2() {
let a = 10;
let a = 1; // 报错
}
fn2() function fn3(x) {
let x;
}
fn3() // 报错 function fn4(x) {
{
let x ;
}
}
fn4() // 不报错

const 关键字

定义:

const声明一个只读的常量。一旦声明,常量的值就不能改变。

注意事项

const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。

const命令的本质

const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

const foo = {};

// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123 // 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

ES6入门(一)的更多相关文章

  1. ES6入门笔记

    ES6入门笔记 02 Let&Const.md 增加了块级作用域. 常量 避免了变量提升 03 变量的解构赋值.md var [a, b, c] = [1, 2, 3]; var [[a,d] ...

  2. es6入门4--promise详解

    可以说每个前端开发者都无法避免解决异步问题,尤其是当处理了某个异步调用A后,又要紧接着处理其它逻辑,而最直观的做法就是通过回调函数(当然事件派发也可以)处理,比如: 请求A(function (请求响 ...

  3. es6入门3--箭头函数与形参等属性的拓展

    对函数拓展兴趣更大一点,优先看,前面字符串后面再说,那些API居多,会使用能记住部分就好. 一.函数参数可以使用默认值 1.默认值生效条件 在变量的解构赋值就提到了,函数参数可以使用默认值了.正常我们 ...

  4. Vue+koa2开发一款全栈小程序(1.课程介绍+2.ES6入门)

    1.课程介绍 1.课程概述 1.做什么? Vue+koa2开发一款全栈小程序 2.哪些功能? 个人中心.图书列表.图书详情.图书评论.个人评论列表 3.技术栈 小程序.Vue.js.koa2.koa- ...

  5. es6入门5--class类的基本用法

    在ES6之前,准确来说JavaScript语言并无类的概念,却有模拟类的做法.相比在类似java这类传统面向对象语言中通过类来生成实例,js则通过构造函数模拟类来生成实例. 这是因为在JS设计初期,作 ...

  6. es6入门6--数组拓展运算符,Array.from()基本用法

    本文只是作为ES6入门第九章学习笔记,在整理知识点的同时,会加入部分个人思考与解答,若想知道更详细的介绍,还请阅读阮一峰大神的ES6入门 一.拓展运算符 ES6中新增了拓展运算(...)三个点,它的作 ...

  7. ES6入门之let和const命令

    前言 大家好,我是一只流浪的kk,当你看到这边博客的时候,说明你已经进入了ES6学习的领域了,从本篇博客开始,我将会将自己学习到ES6的相关知识进行整理,方便大家参考和学习,那么我将带你进入第一节的内 ...

  8. ES6入门之变量的解构赋值(二)

    前言 在上一章 ES6入门之let和const命令中我们对ES6的相关语法已经有了初步了解,上一章中我们主要学习了三大部分的内容,let命令的使用,块级作用域,const命令的使用,那么从本篇博客将进 ...

  9. ES6入门十二:Module(模块化)

    webpack4打包配置babel7转码ES6 Module语法与API的使用 import() Module加载实现原理 Commonjs规范的模块与ES6模块的差异 ES6模块与Nodejs模块相 ...

  10. es6入门7--Set Map数据结构

    本文作为ES6入门第十三章的学习整理笔记,可能会包含少部分个人的理解推测,若想阅读更详细的介绍,还请阅读原文ES6入门 一.set数据结构 1.set不接受重复值 ES6新增了Set构造函数用于创建s ...

随机推荐

  1. @codeforces - 668E@ Little Artem and 2-SAT

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定两个 2-sat 问题,询问两个问题的解集是否相同. 如果不 ...

  2. (五)使用logback进行日志记录

    原文:https://www.cnblogs.com/taiyonghai/p/9290641.html 引入jar包 此处如果是引用了spring boot则不需要再引一下的jar包了,spring ...

  3. python实现装饰器

    #编写一个装饰器 def zs(x): def h(): return ""+x() return h @zs def hhh(): return "你好" p ...

  4. 恕我直言你可能真的不会java第2篇:Java Stream API?

    一.什么是Java Stream API? Java Stream函数式编程接口最初是在Java 8中引入的,并且与lambda一起成为Java开发的里程碑式的功能特性,它极大的方便了开放人员处理集合 ...

  5. 004.OpenShift命令及故障排查

    一 CLI访问OpenShift资源 1.1 资源操作 OCP将OpenShift集群中的为由主节点管理的对象统称为资源,如:node.service.pod.project.deployment.u ...

  6. opencv C++ Mat构造函数

    cv::Scalar scalar1(v); cv::Mat mat3(size,CV_8UC1,scalar1); std::cout<<mat3<<std::endl; s ...

  7. Linux Pam后门总结拓展

    首发先知社区: https://xz.aliyun.com/t/7902 前言 渐渐发现pam后门在实战中存在种植繁琐.隐蔽性不强等缺点,这里记录下学习pam后门相关知识和pam后门的拓展改进. 0x ...

  8. skywalking 5.X 分布式链路跟踪 使用笔记

    skywalking 特点 性能好,针对单实例5000tps的应用,在全量采集的情况下,只增加 10% 的CPU开销.详细评测见<skywalking agent performance tes ...

  9. 多线程高并发编程(12) -- 阻塞算法实现ArrayBlockingQueue源码分析(1)

    一.前言 前文探究了非阻塞算法的实现ConcurrentLinkedQueue安全队列,也说明了阻塞算法实现的两种方式,使用一把锁(出队和入队同一把锁ArrayBlockingQueue)和两把锁(出 ...

  10. Python实用笔记——错误处理

    让我们用一个例子来看看try的机制: try: print('try...') r = 10 / 0 print('result:', r) except ZeroDivisionError as e ...