文章目录

  • 1. 作用域
  • 2. let
  • 3. const

1. 作用域

常见的作用域主要分为几个类型:全局作用域、函数作用域、块状作用域、动态作用域。

对象 类型
global/window 全局作用域
function 函数作用域(局部作用域)
{} 块状作用域
this 动态作用域

全局作用域
变量在函数或者代码块 {} 外定义,即为全局作用域。不过,在函数或者代码块{} 内未定义的变量也是拥有全局作用域的(不推荐)。

var course = "es"// 此处可调用 course 变量
function myFunction() {// 函数内可调用 course 变量
}

如果变量在函数内没有声明(没有使用 var 关键字),该变量依然为全局变量。

// 此处可调用 course 变量function myFunction() {course = "es"// 此处可调用 course 变量
}

以上实例中 course 在函数内,但是拥有全局作用域,它将作为 global 或者 window 的属性存在。

函数作用域
在函数内部定义的变量,就是局部作用域。函数作用域内,对外是封闭的,从外层的作用域无法直接访问函数内部的作用域!

function bar() {var testValue = 'inner'
}console.log(testValue)
// 报错:ReferenceError: testValue is not defined

如果想读取函数内的变量,必须借助 return 或者闭包。

function bar(value) {var testValue = 'inner'return testValue + value
}console.log(bar('fun')) // "innerfun"

闭包的方式:

function bar(value) {var testValue = 'inner'var rusult = testValue + valuefunction innser() {return rusult}return innser()
}console.log(bar('fun')) // "innerfun"

return 是函数对外交流的出口,而 return 可以返回的是函数,根据作用域的规则,函数内部的子函数是可以获取函数作用域内的变量的。

块状作用域
在ES6之前除了全局作用域就是函数作用域,一直没有自己的块状作用域。在 ES6 中已经改变了这个现象,块状作用域得到普及。关于什么是块,只要认识 {} 就可以了。

if (true) {let a = 1console.log(a)
}

在这个代码中, if{}就是“块”,这个里面的变量就是拥有这个块状作用域,按照规则, {}之外是无法访问这个变量的。

动态作用域
在 JavaScript 中很多同学对this的指向时而清楚时而模糊,其实结合作用域会对this 有一个清晰的理解。不妨先来看下这段代码:

window.a = 3function test() {console.log(this.a)
}test.bind({a: 2
})() // 2
test() // 3

在这里bind已经把作用域的范围进行了修改指向了 { a: 2 },而 this 指向的是当前作用域对象。

变量的作用域是在定义时决定而不是执行时决定,也就是说词法作用域取决于源码,通过静态分析就能确定,因此词法作用域也叫做静态作用域。 相反,只能在执行阶段才能决定变量的作用域,那就是动态作用域。

2. let

ES6 新增了let命令,用来声明变量。

1.let 声明的全局变量不是全局对象window的属性

var a = 5
console.log(window.a) // 5
let a = 5
console.log(window.a) // undefined

2.用let定义变量不允许重复声明

var a = 5
var a = 6console.log(a) // 6
let a = 5
let a = 6
// VM131:1 Uncaught SyntaxError: Identifier 'a' has already been declared
//   at <anonymous>:1:1

3.let声明的变量不存在变量提升

function foo() {console.log(a)var a = 5
}foo() //undefined

上述代码中,a 的调用在声明之前,所以它的值是 undefined,而不是 Uncaught ReferenceError。实际上因为 var 会导致变量提升。而对于 let 而言,变量的调用是不能先于声明的:

function foo() {console.log(a)let a = 5
}foo()
// Uncaught ReferenceError: Cannot access 'a' before initialization

4.let声明的变量具有暂时性死区
只要块级作用域内存在let命令,它所声明的变量就绑定在了这个区域,不再受外部的影响。

var a = 5
if (true) {a = 6let a
}
// Uncaught ReferenceError: Cannot access 'a' before initialization

上面代码中,存在全局变量 a ,但是块级作用域内let又声明了一个局部变量a,导致后者绑定这个块级作用域,所以在let声明变量前,对a 赋值会报错。

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

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

5.let 声明的变量拥有块级作用域

let实际上为 JavaScript 新增了块级作用域

{let a = 5
}
console.log(a) // undefined

a 变量是在代码块 {} 中使用let定义的,它的作用域是这个代码块内部,外部无法访问。

3. const

不能被改变的叫做常量,ES5中定义一个常量:

Object.defineProperty(window, 'PI', {value: 3.14,writable: false
})
console.log(PI)
PI = 5
console.log(PI)

const除了具有let的块级作用域和不会变量提升外,还有就是它定义的是常量,在用 const定义变量后,我们就不能修改它了,对变量的修改会抛出异常

const PI = 3.1415
console.log(PI)
PI = 5
console.log(PI)
// Uncaught TypeError: Assignment to constant variable.

这个代码块中因为对 PI 尝试修改,导致浏览器报错,这就说明 const 定义的变量是不能被修改的,它是只读的。

注意:const 声明的变量必须进行初始化,不然会抛出异常 Uncaught SyntaxError: Missing initializer in const declaration。

需要注意的是,const 实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。

const obj = {name: 'xiaoming',age: 18
}
obj.school = 'qinghua'
console.log(obj)
// {name: "xiaoming", age: 18, school: "qinghua"}

虽然定义的对象是const,但是只是保证地址值不变,地址指向的内存空间的值是可以变的。

如何让对象或者数组这种引用数据类型也不被改变呢?

Object.freeze(obj)
// 只是浅层冻结,只会对最近一层的对象进行冻结,并不会对深层对象冻结。

【ES6(2015)】新的声明方式 let、const相关推荐

  1. ES6学习笔记二 新的声明方式和变量的解构赋值!

    新的声明方式 在ES5的时候,我们只有一个声明方式,var!但是在es6中,声明进行了扩展,我们加上ES5的var的申明方式,我们有了三种声明方式: var:它是variable的简写,可以理解成变量 ...

  2. ES6系列_2之新的声明方式

    ES6系列_2之新的声明方式 在ES5中我们在声明时只有一种方法,就是使用var来进行声明,ES6对声明的进行了扩展,现在可以有三种声明方式. (1)var:它是variable的简写,可以理解成变量 ...

  3. 必须声明标量变量 @sum_level。_ES6系列—新的变量声明方式

    在ES5中,变量声明只有var和function以及隐式声明三种,在ES6中则增加了let.const.import和class四种. 1. let 1.1 块级作用域 let声明的变量的作用域是块级 ...

  4. 三、const常量声明方式

    cosnt是es6中常量的声明方式,声明方法和var.let声明方式一样,但是有点不同的是,const声明方式必须立即初始化变量,并且也不能在后面改变他的值 const foo; // SyntaxE ...

  5. ES6学习笔记02:let 与 const

    ES6学习笔记02:let 与 const 用var声明的变量会造成全局污染,于是就产生了新的声明方式. 1.let 用let声明变量,必须先声明后使用. 在for循环头里用let定义循环变量i,那么 ...

  6. ES6 — ES11 新特性一篇通

    一.ES6 1.1.let 变量不能重复声明 有块级作用域 不存在变量提升(必须先声明后使用) 不影响作用域链 <script>//声明变量let a;let b, c, d;let e ...

  7. ES6~ES12新特性

    ES6新特性 let属性 <div class="item">记得刷卡</div> <script type="text/javascrip ...

  8. TypeScript学习(2)-变量声明 var let const

    let.const是js中新的变量声明方式,es5,es6新版本的js语言规范出来的定义,弥补了var的缺陷.const是对let的一个增强,不允许对一个变量再次赋值,一般用于常量. 使用var声明的 ...

  9. 【面试】HTML5 有哪些新特性?_声明方式

    最近看了一些与html基础相关的入门教学视频,心得感悟只有:不同特性的标签记住就好了!但理智告诉我,一切还未正式开始.肿么办?-_-# 是不是可以根据具体html的面试问题对理论知识进行认知拓展与实践 ...

最新文章

  1. 什么是标签传播算法?为什么要使用标签传播算法?如何使用?
  2. tomcat 之APR优化
  3. 使用信号量实现进程间同步
  4. (转)mysql帮助命令使用说明
  5. CAT 性能优化的实践和思考
  6. python同时发大量请求_python http服务器,多个同时请求
  7. 【NLP】jieba分词-Python中文分词领域的佼佼者
  8. 通过mysqlnow()函数校正本地(windows)时间与服务器(linux)时间
  9. Servlet教程第8讲笔记
  10. iOS 各种证书的作用、有效期、过期的后果和解决办法
  11. mysql nfs存储_NFS存储服务及部署
  12. JAVA我的世界给op_我的世界OP指令有哪些 OP权限怎么设置
  13. js -- others
  14. 大数据时代比较教育研究范式的转型
  15. 在线学生信息管理平台
  16. oracle安装包,psu,ru补丁包下载文档
  17. 5G与物联网技术趋势分析
  18. JAVA8 stram 实战
  19. 【天池】金融风控数据挖掘task1
  20. 关于wps相同字体大小在不同文档显示不同的问题解决

热门文章

  1. 一步一步写算法(之 算法总结)【转】
  2. linux下C调用lua的第一个程序
  3. 【HDOJ】4541 Ten Googol
  4. 高效程序猿之(三)VS2010快捷键(转)
  5. 【转】vc6.0移植到VS2010遇到的问题,散分给大家,虽然分不多,各位帮忙
  6. 获取本机IP(考虑多块网卡、虚拟机等复杂情况)
  7. Label显示多行文本总结
  8. 大一萌新看过来,“这样”学C++,让你不再迷茫!
  9. Eclipse 远程调试
  10. 于连生性聪颖的飞鸽传书