什么是作用域

块级作用域:即在{}花括号内的域,由{ }包括,比如if{}块、for(){}块。注意函数快也叫做块

函数作用域:变量在声明它们的函数体以及这个函数体嵌套的任意函数体都是有定义的。

JS中作用域有:全局作用域、函数作用域,是没有块作用域的。

块级作用域是ES6中的。

什么是undefined

Undefined类型只有一个值,即undefined。当声明的变量还未被初始化时,变量的默认值为undefined。
Null类型也只有一个值,即null。null用来表示尚未存在的对象,常用来表示函数企图返回一个不存在的对象。

js 代码

这段代码显示为true,代表oVlaue的值即为undefined,因为我们没有初始化它。

js 代码

当页面上不存在id为"notExistElement"的DOM节点时,这段代码显示为"true",因为我们尝试获取一个不存在的对象。

js 代码

第一行代码很容易理解,undefined的类型为Undefined;第二行代码却让人疑惑,为什么null的类型又是Object了呢?其实这是JavaScript最初实现的一个错误,后来被ECMAScript沿用下来。在今天我们可以解释为,null即是一个不存在的对象的占位符,但是在实际编码时还是要注意这一特性。

js 代码

ECMAScript认为undefined是从null派生出来的,所以把它们定义为相等的。但是,如果在一些情况下,我们一定要区分这两个值,那应该怎么办呢?可以使用下面的两种方法。

js 代码

下面进入正题

1.直观上

var的作用域要大一些,由于var的作用域是函数级作用域所以var不受块级的约束,对于var声明的变量,只有函数才能为它创建新的作用域.

{var a = "DOMAIN";}console.log(a)//"DOMAIN"

有了let之后,才可以像C语言一样,直接就是:

{let a = "DOMAIN";}console.log(a)//Error: a is not defined

2.变量提升

先上一个简单的例子:

console.log(a);//undefined

var a = "hey I am now hoisting";

我们在a被声明前调用a,没有报错,反而是返回一个undefined值,原因是:a其实已经在调用前被声明了,只是没有被初始化。JavaScript会把作用域里的所有变量和函数提到函数的顶部声明,相当于:

var a;
console.log(a);//undefined
a = "hey I am now hoisting";

JavaScript会使用undefined缺省值创建变量a,注意,事实上浏览器并没有把声明语句放到作用域的顶部,在编译阶段,控制流进入域,该域所有的变量和函数的声明先进入内存,文中代码的相对位置不会变动的。

由此可以知道,变量提升指的是变量声明的提升,不会提升变量的初始化和赋值。

3.let变量暂时性死区现象

首先明确一点,变量var与let都存在变量提升现象

let变量必须在声明后使用,否则会报错。console.log(aLet)抛出了一个错误,浏览器认为aLet并没有声明,这是否意味着let并没有使a变量提升呢?

console.log(aVar); // undefined
console.log(aLet); // causes ReferenceError: aLet is not defined
var aVar = 1;
let aLet = 2;

再看一个例子

let a = "hey I am outside";
if(true){
console.log(a);//"hey I am outside"
}

if{}块内打印全局let变量,很正常

let a = "hey I am outside";
if(true){
console.log(a);//Uncaught ReferenceError: a is not defined
let a = "hey I am inside";
}

注意看,这里同样抛出了一个错误,认为a没有声明,但是,如果a没有变量提升,执行到console.log时应该是输出全局作用域中的a,而不是出现错误

Temporal Dead Zone (TDZ) 翻译为中文即为 暂时性死区

先看一段 MDN 上关于暂时性死区的定义

let bindings are created at the top of the (block) scope containing the declaration, commonly referred to as “hoisting”. Unlike variables declared with var, which will start with the value undefined, let variables are not initialized until their definition is evaluated. Accessing the variable before the initialization results in a ReferenceError. The variable is in a “temporal dead zone” from the start of the block until the initialization is processed.

文档第一句话就明确指出 let 存在变量提升,但是与 var 不同的是,var 的变量提升的同时会默认赋值为 undefined. 而 let 仅仅发生了提升而已,并不会赋任何值给变量,在显式赋值之前,任何对变量的读写都会导致 ReferenceError 的报错。

最重要的是从代码块(block)起始if(true){位置到变量求值(包括赋值)let a = "hey I am inside";这之间的这块区域,称为该变量的暂时性死区。在死区中,禁止访问该let变量

比较var和let的区别的更多相关文章

  1. 简述C#中关键字var和dynamic的区别

    C#中关键字var和dynamic的区别如下: 1.var申明的变量必须初始化,dynamic申明的变量无需初始化. 2.var关键字只能在方法内部申明局部变量,dynamic关键字可用于局部变量,字 ...

  2. var, object, dynamic的区别以及使用(转载)

    var, object, dynamic的区别以及使用 阅读目录: 一. 为什么是它们三个 二. 能够任意赋值的原因 三. dynamic的用法 四. 使用dynamic的注意事项 拿这三者比较的原因 ...

  3. var, object, dynamic的区别以及dynamic的使用

    var, object, dynamic的区别以及dynamic的使用 理解C# 4 dynamic(1) - var, object, dynamic的区别以及dynamic的使用 2013-06- ...

  4. var与let的区别

    var与let的区别 前言: 在没接触Es6之前,我们在js中声明都是通过var来声明变量的,var声明变量虽说方便,但是,又有一些自己的诟病,下边来说一说,这三个的区别! var var相信大家都不 ...

  5. var let const 的区别

    Var let const 的区别 1.Var 定义的变量存在变量提升,而了let和const不存在变量提升.即在定义的变量代码上使用该变量,var的会输出undefined,而let的会报错. 2. ...

  6. JavaScript中函数function fun(){}和 var fun=function(){}的区别

    function fun(){} 和 var fun=function(){}的区别 标题有点长···· 废话少说,其实他们的主要区别就是"函数声明的提前行为". var fun= ...

  7. JS中const、var 和let的区别

    今天第一次遇到const定义的变量,查阅了相关资料整理了这篇文章.主要内容是:js中三种定义变量的方式const, var, let的区别. 1.const定义的变量不可以修改,而且必须初始化. 1 ...

  8. Javascript var 和 let 的区别

    Javascript var 和 let 的区别 var 是函数块的全局变量. let 是代码块的局部变量. let 变量不会提升,如果先使用后定义会 undefind. 参考: https://de ...

  9. es6的let与es5的var定义变量的区别

    es6的let与es5的var定义变量的区别 自身新手第一次接触let关键字的时候,不知道let与var的区别,本能认为是一样,但非如此,比如下述的代码运行就会报错: let hello = 'hel ...

  10. var, object, dynamic的区别以及使用

    var, object, dynamic的区别以及使用 阅读目录: 一. 为什么是它们三个 二. 能够任意赋值的原因 三. dynamic的用法 四. 使用dynamic的注意事项 拿这三者比较的原因 ...

随机推荐

  1. 2023年3月份至2024年3月份CCF会议情况——人工智能领域

    April 2, 2023:          https://2023.ecmlpkdd.org/submissions/key-dates-deadlines/ ECML-PKDD (Europe ...

  2. SMU Summer 2023 Contest Round 13

    SMU Summer 2023 Contest Round 13 A. Review Site 我们总是可以把差评放到另一个服务器,好评和中立放另一个,这样最多投票数就是好评与中立数 #include ...

  3. 【CMake系列】05-静态库与动态库编译

    在各种项目类型中,可能我们的项目就是一个 库 项目,向其他人提供 我们开发好的 库 (windows下的 dll /lib : linux下的 .a / .so):有时候在一个项目中,我们对部分功能 ...

  4. P4823 [TJOI2013] 拯救小矮人

    感觉这个题的操作很新奇,做个记录. P4823 [TJOI2013] 拯救小矮人 大概题面: 一群小矮人掉进了一个很深的陷阱里,由于太矮爬不上来,于是他们决 定搭一个人梯.即:一个小矮人站在另一小矮人 ...

  5. JAVA学习——JDK开发环境配置

    2024/07/08 一.JDK下载 二.安装与JDK开发环境配置(Windows) 三.安装与JDK开发环境配置(Linux) 一.JDK下载与安装 网址: https://www.oracle.c ...

  6. 使用 nuxi add 快速创建 Nuxt 应用组件

    title: 使用 nuxi add 快速创建 Nuxt 应用组件 date: 2024/8/28 updated: 2024/8/28 author: cmdragon excerpt: 通过使用 ...

  7. 【YashanDB知识库】字段加上索引后,SQL查询不到结果

    [标题]字段加上索引后,SQL查询不到结果 [问题分类]索引功能使用 [关键字]索引,SQL查询,时间类型,vachar字符类型 [问题描述]字段加上索引后,SQL查询不到结果. [问题原因分析]当前 ...

  8. 如何在 Nuxt 3 中有效使用 TypeScript

    title: 如何在 Nuxt 3 中有效使用 TypeScript date: 2024/9/9 updated: 2024/9/9 author: cmdragon excerpt: 摘要:本文详 ...

  9. TreeMap源码详解—彻底搞懂红黑树的平衡操作

    介绍 TreeSet和TreeMap在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也就是说TreeSet里面有一个TreeMap(适配器模式). Java TreeMap实现了Sorted ...

  10. SQL Server CTE (Common Table Expression) 公用表表达式

    参考: Sql - CTE公用表表达式和With用法总结 YouTube – SQL WITH Clause | How to write SQL Queries using WITH Clause ...