let const var区别
创始人
2024-02-19 09:19:52

文章目录

      • 写在前面
      • 1.var关键字
        • 1.1 没有块级作用域的概念,有全局作用域、函数作用域的概念
        • 1.2 存在变量提升
        • 1.3 全局作用域用var声明的变量会挂载到window对象上
        • 1.4 同一作用域中允许重复声明
        • 1.5 不初始化值默认为undefined
      • 2.let关键字
        • 2.1 有块级作用域的概念
        • 2.2 不存在变量提升
        • 2.3 同一作用域内不允许重复声明
        • *2.4 暂时性死区(dead zone)
      • 3.const关键字
        • 3.1 创建后必须立即初始化,不能留到以后赋值
        • *3.2 创建常量
          • 3.2.1 es5实现创建常量
          • 3.2.1 实现const创建的引用类型为常量

写在前面

该格式的文字为个人理解,纯大白话

文章标题前加* 代表该知识点为不好理解或容易遗漏的知识点

1.var关键字

1.1 没有块级作用域的概念,有全局作用域、函数作用域的概念

例1:

//Global Scope
{var a = 10;
}
console.log(a);  //10

在大括号内部声明a,在大括号外部仍然可以访问,由此可以看出var声明的变量不存在块级作用域(Block Scope)的概念

例2:

//Global Scope
var a = 10;
function checkscope(){//Local Scopevar b = 20;console.log(a);  //10console.log(b);  //20
}
checkscope();
console.log(b);  //ReferenceError: b is not defined

上面代码中,在 Global Scope 中用 var 声明了 a,在 checkscope 函数中的 Local Scope(本地作用域、函数作用域)中打印出了 10,但是在 Global Scope 中打印的变量 b 报错了。

在全局中声明了a,存在全局作用域中,函数(checkscope)内部也可以访问。在函数(checkscope)内部声明的变量,仅存在与函数内部作用域中,函数外无法访问

1.2 存在变量提升

例3:

//Global Scope
console.log(a);  //undefined
var a = 10;checkscope();
function checkscope(){//Local Scopeconsole.log(a);  //undefinedvar a;
}

先打印了a,然后用var声明变量a,打印结果为undefined。
变量提升是因为js需要经理编译和执行阶段。js在编译阶段的时候,会搜集所有的变量声明并且提前声明变量

1.3 全局作用域用var声明的变量会挂载到window对象上

//Global Scope
var a = 10;
console.log(a);  //10
console.log(window.a);  //10
console.log(this.a);  //10

上面代码中,打印出了 310,访问 awindow.a 或是 this.a 都是等价的。
举个例子:比如我要访问 location 对象,使用 location 可以访问,使用 window.location 也可以访问,只不过 window 对象可以省略不写,就像 new Array( )new window.Array( ) 是等价的。

1.4 同一作用域中允许重复声明

//Global Scope
var a = 10;
var a = 20;
console.log(a);  //20checkscope();
function checkscope(){//Local Scopevar b = 10;var b = 20;console.log(b);  //20
}

上面代码中,在 Global Scope 中声明了 2a,以最后一次声明有效,打印为 20。同理,在 Local Scope 也是一样的。

1.5 不初始化值默认为undefined

//Global Scope
var a;
console.log(a);  //undefined

Global Scope 中用 var 声明了 a,但没有初始化值,它的值默认为 undefined
这里是 undefinedundefined 类型,而不是字符串。

2.let关键字

2.1 有块级作用域的概念

{//Block Scopelet a = 10;
}
console.log(a);  //ReferenceError: a is not defined

在大括号内声明的变量,在大括号外无法被访问

2.2 不存在变量提升

 console.log(a);  // Uncaught ReferenceError: a is not definedlet a = 10;

上面代码中,打印 a 报错:无法在初始化之前访问。说明不存在变量提升。

2.3 同一作用域内不允许重复声明

{//Block Scopelet A;var A;  //SyntaxError: Identifier 'A' has already been declared
}
{//Block Scopevar A;let A;  //SyntaxError: Identifier 'A' has already been declared
}
{//Block Scopelet A;let A;  //SyntaxError: Identifier 'A' has already been declared
}

*2.4 暂时性死区(dead zone)

在作用域内第一行到使用let、const声明语句之间,存在暂时性死区,访问该变量就会报错。

ECMAScript2015文档中的解释:
当程序的控制流程在新的作用域(module、functionblock 作用域)进行实例化时,在此作用域中用 let/const 声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在这运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区。

个人理解:let/const 命令会使区块形成封闭的作用域,在此作用域中,let/const* 声明的变量会先在作用域中被创建,一直到变量被声明之前,该变量都是不可用的,访问就会报错。在语法上称为 “暂时性死区”temporal dead zone,简称 TDZ

if (true) {//暂时性死区(TDZ)开始console.log(a);  //ReferenceError: Cannot access 'a' before initializationlet a; //暂时性死区(TDZ)结束console.log(a);  //undefineda = 123;console.log(a);  //123
}

例4:

{//Block Scopeconsole.log(a);  //ReferenceError: Cannot access 'a' before initializationlet a = 20;
}

专属报错:初始化之前无法访问
在这里插入图片描述
区别:

这里的暂时性死区存在于块级作用域中,若在全局作用域中,则报错‘is not defined’

在这里插入图片描述

3.const关键字

const除了具有以上let中的四种特性(存在块级作用域、不存在变量提升、同一作用域内不允许重复声明、存在暂时性死区)之外,还有以下特点:

3.1 创建后必须立即初始化,不能留到以后赋值

在这里插入图片描述
const 声明的变量 a 没有进行初始化,所以报错。

*3.2 创建常量

const创建常量的特点:

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

例5:
在这里插入图片描述

const 创建的变量的内存地址不可改变,而对于简单的数据类型,值就存在于变量指向的内存地址中,所有a的值不可以改变
例6:
在这里插入图片描述
对于复杂的数据类型,内存地址中保存的是一个指针,const只能保证这个指针是固定的,指针指向的数据结构是可以改变的

3.2.1 es5实现创建常量

Object.defineProperty
三个参数:

  1. 属性所在的对象
  2. 属性的名字
  3. 一个描述符对象:
    • configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,默认值为false。
    • enumerable:表示能否通过for in循环访问属性,默认值为false
    • writable:表示能否修改属性的值。默认值为false。
    • value:包含这个属性的数据值。默认值为undefined。

实现:

Object.defineProperty(window,"args",{
value: ' this is es5',
writable: false
})

报错:常量变量赋值
在这里插入图片描述

3.2.1 实现const创建的引用类型为常量
const obj={id:1,age:18,name:'aaa'
}obj.age=19       // cosnt 创建一个对象,对象中的属性可以被改变

追问1:如何使对象中的属性不可改变
解决:使用Object.freeze(),冻结对象,一个被冻结的对象再也不能被修改

const obj2={id:2,name:'bbb',age:20,food:['banana','apple']
}
Object.freeze(obj2)obj2.age=21                 //被Object.freeze()冻结后,不可以改变    
obj2.foods[1]='pear'        //可以改变  freeze只能冻结根层 嵌套引用类型需要嵌套递归

解决:实现创建引用类型
思路:使用递归,将每一层的引用类型冰冻,实现创建引用类型的常量。

   function deepFreeze(obj) {Object.freeze(obj);(Object.keys(obj) || []).forEach((key) => {let innerObj = obj[key]if (typeof innerObj === 'object') {deepFreeze(innerObj);}})}const tempObj = {id: 23,name: '1',food: ['banana', 'apple']}deepFreeze(tempObj)

相关内容

热门资讯

北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...