ES6学习教程之块级作用域详解

前言

众所周知ES5之前javascript语言只有函数作用域和全局作用域,使用var来声明变量,var声明的变量还存在变量提升使人困惑不已。我们先来复习一下ES5的var声明,再对比学习let和const 。

var

var声明之函数作用域和全局作用域。

来段代码体会一下:

function getName() {
 if (1 + 1 === 2) {
 var name = 'xixi';
 }

 console.log(name);
}

getName();//xixi

在c或java语言中name本应该只在if块中使用的,但是在if的外面也可以访问到,这个就是 js没有块级作用域的一种体现。这个弊端在for循环中体现的十分明显:

for (var i = 0; i < 10; i ++) {
 // ...
}

console.log(i);// 10

var i的本意是声明个临时变量i,用来遍历数组等,本不应该在for循环的外部访问到,但现在却可以被访问到你说闹不闹心?好一点的程序员会用立即执行函数来模拟块级作用域,原来的我会注意一下尽量不使用相同的变量名😎。

(function() {
 for (var i = 0; i < 10; i ++) {
 // ...
 }
})();

console.log(i);// undefined

以上:大家知道了 js 没有块级作用域。

变量可以重复声明

var name = 'xixi';
console.log(name);// xixi
var name= '一步';
console.log(name);// 一步

不报错,困惑不困惑,这个就是变量可以重复声明。

变量提升

function getName() {
 console.log(name);
 var name = 'xixi';
 // ...
}

getName();// undefined

console.log打印name为undefined。为啥不报错呢,对于一直使用js语言的人来说这个现象还好理解,如果是后台转前端的人来说估计得骂人了。这就是所谓的变量提升。简单的向大家解释一下吧。

var name = 'xixi';

这是一条被我们写烂了的语句,包含两个过程:var name; name = 'xixi';分别为变量声明和变量初始化。

变量提升: 无论变量声明var name;处于什么位置,都会被提到作用域的顶部进行。

let

ES6为让变量生命周期更加可控,引入两个非常好的特性let、const。块级作用域、不能重复声明、临时性死区等特性用来解决 var 变量存在的种种问题。

块级作用域

function getName4ES6() {
 if (1 + 1 === 2) {
 let name = 'xixi';
 }

 console.log(name);
}

getName4ES6(); // undefined

终于在{}外面访问不到name了。for循环也变的简单了,大家试一下将for循环的var换成 let.

同一块级作用域内不能重复声明变量

function redefineValue() {
 let name = 'xixi';
 let name = '一步';
}

redefineValue();// Uncaught SyntaxError: Identifier 'name' has already been declared

重复声明会报错

{
 let name = 'xixi';
 console.log(name);// xixi
 {
 let name = 'yibu';
 console.log(name); // yibu
 }
}

注意: 在 ES6中,{}就是一个块级作用域。

临时性死区

function getName4ES6() {
 console.log(name);
 for (let i = 0; i < 10; i ++) {

 }
 let name = 'xixi';
 // ...
}

getName4ES6();// Uncaught ReferenceError: name is not defined

在上文ES5中,name还会存在变量提升,值为undefined。ES6中又报错了。怎么解释呢?。。。。这个就是临时性死区的概念,在作用域块中不可以在变量声明前就使用变量,若使用是会出错的。

javascript引擎在发现变量声明时,要么将变量声明提升到作用域的顶部(var声明变量时),要么将变量放在临时性死区中(let、const声明变量时),访问临时性死区中的变量会触发运行时错误。

const

const和let同样具有块级作用域,不能重复声明,临时性死区的概念。它还具有两个特有的特性:声明的同时必须初始化、变量引用不可以改变。

声明的同时必须初始化

const name;//Uncaught SyntaxError: Missing initializer in const declaration

不赋值,就报错。这个也很好理解const的本意就是用来定义常量,不可变的值。若不在声明时给出初始值以后就再也没有机会了。

值不可变

const name = 'x9x9';
name = 'yyy';// Uncaught SyntaxError: Invalid or unexpected token

那么对象会怎样呢?

const person = {
 name: 'lala',
 age: 40
};

person = {};// VM1042:6 Uncaught TypeError: Assignment to constant variable. at <anonymous>:6:8

引用是不可变的,那我们在看看对象的属性值是什么情况吧~

person.name = 'yoyo';
console.log(person);// {name: "yoyo", age: 40}

没有报错,对象引用不可改变,对象属性可以变更。

let vs const

大家可能会困惑,什么时候使用let,什么时候使用const。let能做的const好像都可以。网上有一种流行做法:能用const就绝不用let,简单粗暴,不过很好用。

个人看法:若变量在后续方法中会被改变,就使用let。一些常量声明使用const, const声明的变量名全部大写。代码中的变量,如果是let声明的就代表其可变,若是const声明的,不论是简单数据类型还是引用类型变量就都不要改变它的值。这样,程序会更加的健壮,大家合作起来也比较方便。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • JavaScript的作用域和块级作用域概念理解

    作用域永远都是任何一门编程语言中的重中之重,因为它控制着变量与参数的可见性与生命周期.讲到这里,首先理解两个概念:块级作用域与函数作用域. 什么是块级作用域呢? 任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域. 函数作用域就好理解了(*^__^*) ,定义在函数中的参数和变量在函数外部是不可见的. 大多数类C语言都拥有块级作用域,JS却没有.请看下文demo: //C语言 #include <stdio.h> void mai

  • 为什么JavaScript没有块级作用域

    最近在看ES2015 实战,里面有句话是这么说的 JavaScript 中没有块级作用域 可能会对这个问题大家可能有点不理解,先看个例子 var a = [] for(var i = 0; i < 10; i++){ a[i] = function(){ console.log(i); } } a[6](); 我想很多人会觉得这个问题的结果是6,然而很不幸,答案是10.在试试别的呢.a[7]().a[8]().a[8]()结果都是10!! 由于JS在处理primitive的变量的时候,很多时候会

  • 深入理解ES6学习笔记之块级作用域绑定

    众所周知,js中的var声明存在变量提升机制,因此ESMAScript 6引用了块级作用域来强化对变量生命周期的控制 let const 声明不会被提升,有几个需要注意的点 1.不能被重复声明 假设作用域中已经存在某个标识符(无论该标识符是通过var声明还是let.const变量声明),此时再使用let或const关键定声明会抛错 var count=10 let count=20// 此处则会抛出错误,因为同一作用域内不能重复声明 如果当前作用域内嵌另一个作用域,便可在内嵌的作用域中用let声

  • ES6使用let命令更简单的实现块级作用域实例分析

    本文实例讲述了ES6使用let命令更简单的实现块级作用域.分享给大家供大家参考,具体如下: let 带来了更简单的块级作用域 1. ES6新增了let命令,用于声明变量.其与var的不同在于,用let声明的变量只在 { } 内有效.这使得我们可以很方便的实现块级作用域,不再使用立即实行函数. { let a=1; var b=2; } console.log(a); //undefined console.log(b); //2 在for循环中使用let可以有效避免全局变量污染. 2. let不

  • ES6学习教程之块级作用域详解

    前言 众所周知ES5之前javascript语言只有函数作用域和全局作用域,使用var来声明变量,var声明的变量还存在变量提升使人困惑不已.我们先来复习一下ES5的var声明,再对比学习let和const . var var声明之函数作用域和全局作用域. 来段代码体会一下: function getName() { if (1 + 1 === 2) { var name = 'xixi'; } console.log(name); } getName();//xixi 在c或java语言中na

  • ES6学习教程之对象的扩展详解

    一. 属性的简洁表示法 ES6允许直接写入变量和函数作为对象的属性和方法.意思就是说允许在对象中只写属性名,不用写属性值.这时,属性值等于属性名称所代表的变量.下面分别举一个例子来说明: 属性: function getPoint(){ var x = 1 ; var y = 2; return {x,y} } 等同于 fucntion getPoint(x,y){ var x = 1 ; var y = 2; return {x:x,y:y} } 测试: getPoint();//{x:1,y

  • ES6学习教程之对象字面量详解

    前言 本文主要给大家介绍了关于ES6对象字面量的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. ECMAScript6使得声明对象字面量更加简单,提供了属性简写和方法简写功能,属性名计算的新特性. function getInfo(name, age, weight) { return { // 如果属性名和属性值同名可以利用.es6的属性简写 name, // 等同于 make: make age, // 等同于 model: model weight, // 等同

  • Go语言学习教程之反射的示例详解

    目录 介绍 反射的规律 1. 从接口值到反射对象的反射 2. 从反射对象到接口值的反射 3. 要修改反射对象,该值一定是可设置的 介绍 reflect包实现运行时反射,允许一个程序操作任何类型的对象.典型的使用是:取静态类型interface{}的值,通过调用TypeOf获取它的动态类型信息,调用ValueOf会返回一个表示运行时数据的一个值.本文通过记录对reflect包的简单使用,来对反射有一定的了解.本文使用的Go版本: $ go version go version go1.18 dar

  • RxSwift学习教程之类型对象Subject详解

    前言 在上一篇文章我们介绍了 Observable 的基本概念和使用情形.但是大多数情形下,我们需要在应用运行时添加数据到 Observable 中并将其发送给订阅者.在这种需求场景下,我们就不得不使用 RxSwift 中另一种类型对象了 - Subject . 在应用中 Subject 实际上同时扮演了两个不同的角色:既是可观察对象同时也是观察者.这意味着 Subject 实例对象既可以接收事件也可以发送事件.例如,Subject 实例对象可以接收 next 事件信息,然后再将其发送给它自己的

  • Struts2学习教程之输入校验示例详解

    前言 数据校验几乎是每个应用都要做的工作.用户输入的数据,发送到服务器端,天知道用户输入的数据是否是合法的,是否为恶意输入.所以一个健壮的应用系统必须对用户的输入进行校验,将非法的输入阻止在应用之外,防止这些非法的输入进入系统,从而保证系统的稳定性.安全性. 我们都知道,为了更好的用户体验,以及更高的效率,现在的Web应用都存在以下两重数据校验: 客户端数据校验 服务器端数据校验 对于客户端数据校验主要是通过JavaScript代码来完成:而对于服务器端数据校验是整个应用阻止非法数据的最后防线,

  • 正则表达式学习教程之回溯引用backreference详解

    本文实例讲述了正则表达式回溯引用backreference.分享给大家供大家参考,具体如下: 在所有例子中正则表达式匹配结果包含在源文本中的[和]之间,有的例子会使用Java来实现,如果是java本身正则表达式的用法,会在相应的地方说明.所有java例子都在JDK1.6.0_13下测试通过. 一.问题引入 一个在HTML页面中匹配标题标签(H1-H6)的问题: 文本: <body> <h1>Welcome to my page</H1> Content is divid

  • 深入理解es6块级作用域的使用

    一.var 声明与变量提升机制 在JavaScript中使用var定义一个变量,无论是定义在全局作用域函数函数的局部作用域中,都会被提升到其作用域的顶部,这也是JavaScript定义变量的一个令人困惑的地方.由于es5没有像其它类C语言一样的块级作用域,因此es6增加了let定义变量,用来创建块级作用域. 我们来看一个var定义变量的示例: function setName(){ if(condition){ var name = 'loho'; console.log(name); }els

随机推荐