什么是作用域

块级作用域:即在{}花括号内的域,由{ }包括,比如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. 记录一次Ubuntu20.04死机经过!!!在Ubuntu下使用Chrome的“无痕式”窗口,如果打开标签页过多就会造成死机

    这里要说的事情就是自己刚刚经历的事情,而且尝试了多次最后证明,在Ubuntu下使用Chrome的"无痕式"窗口,如果打开标签页过多就会造成死机. 如何在Ubuntu下安装Chrom ...

  2. 读论文《IMPALA: Scalable Distributed Deep-RL with Importance Weighted Actor-Learner Architectures》

    论文地址: https://arxiv.org/pdf/1802.01561v2.pdf 论文<IMPALA: Scalable Distributed Deep-RL with Importa ...

  3. vue 文件流下载

    /**  * 文件转为文件流  * @param {file} file //文件  */ export function getFileBlob(file) {   var dataUrl   va ...

  4. 在LCD上的任意位置显示一张任意大小的jpg图片

    /************************************************* * * file name:lcdshowjpg.c * author :momolyl@126. ...

  5. 如何不用加法符号计算a+b 的值?

    目前为止只有一种思路:位运算+递归小操作 a+b的值可以等价于a^b+(a&b)<<1,也就是a异或b的值加上a与b的值再左移一位.a异或b的值被叫做非进位求和,(a&b) ...

  6. 【全】CSS动画大全之按钮【c】

    效果预览 代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> < ...

  7. Word格式刷快捷键失效恢复方法

    突然某天写材料的时候发现word格式刷快捷键变成了Ctrl+Alt+C和Ctrl+Alt+V,用着这个别扭,于是探索如何改回Ctrl+Shift+C和Ctrl+Shift+V,下边是步骤记录. 打开w ...

  8. JavaScript设计模式样例十七 —— 迭代器模式

    迭代器模式(Itrator Pattern) 定义:用于顺序访问集合对象的元素,不需要知道集合对象的底层表示.目的:提供一种方法顺序访问一个聚合对象中各个元素, 而又无须暴露该对象的内部表示.场景:$ ...

  9. **错误积累&&防止GG写法总结

    19.3.20 关于int与ll 1.如果一道题时间充足,把全部变量定义成long long 2.特别注意最上面宏定义的变量类型,特别是FOR 3.如果是int,用1LL* ...... **实例,让 ...

  10. centos7.5离线安装zabbix4.0

    一.配置环境 1.1 Linux环境说明 zabbix 安装要求 https://www.zabbix.com/documentation/4.0/zh/manual/installation/req ...