精华内容
下载资源
问答
  • 为什么var可以重复声明

    千次阅读 2019-02-26 22:37:08
    答 因为编辑器会在判断有已经声明的同名变量时忽略var,然后直接赋值 原理 在JS代码运行过程中: ...当我们执行上面的代码时,我们可以简单的理解新变量分配一块儿内存,命名a,并赋值2,...

    因为编辑器会在判断有已经声明的同名变量时忽略var,然后直接赋值

    原理

    在JS代码运行过程中:

    • 引擎负责整个代码的编译以及运行
    • 编译器则负责词法分析、语法分析、代码生成等工作
    • 作用域负责维护所有的标识符(变量)。
    var a = 2;
    var a = 3;
    a = 4;
    alert(a); // 4
    

    当我们执行上面的代码时,我们可以简单的理解为新变量分配一块儿内存,命名为a,并赋值为2,但在运行的时候编译器与引擎还会进行两项额外的操作:判断变量是否已经声明

    1. 重复声明时:首先编译器对代码进行分析拆解,从左至右遇见var a,则编译器会询问作用域是否已经存在叫a的变量了。如果不存在,则招呼作用域声明一个新的变量a;若已经存在,则忽略 var 继续向下编译,这时 a = 2被编译成可执行的代码供引擎使用。
    2. 赋值时:引擎遇见a=2时同样会询问在当前的作用域下是否有变量a。若存在,则将a赋值为2(由于第一步编译器忽略了重复声明的var,且作用域中已经有a,所以重复声明会发生值的覆盖而不会报错);若不存在,则顺着作用域链向上查找,若最终找到了变量a则将其赋值2,若没有找到,则招呼作用域声明一个变量a并赋值为2(这就是为什么第二段代码可以正确执行且a变量为全局变量的原因,当然,在严格模式下JS会直接抛出异常:a is not defined)。
    展开全文
  • let和const声明的变量不可以重复声明 let和const声明的变量存在暂时性死区 const声明的基础类型不可修改,const声明的引用类型只能修改该引用类型的属性而不能给该变量重新赋值(const确定了一个地址,该地址不能...

    在面试时,面试官往往会问到var,let,const的区别是什么?我想大多数人对这个问题都心有成竹,你的答案大概都会包含在下面:

    • var存在变量提升,而let和const不存在变量提升
    • var声明的变量会添加进window对象中,而let和const声明的变量不会
    • let和const声明的变量不可以重复声明
    • let和const声明的变量存在暂时性死区
    • const声明的基础类型不可修改,const声明的引用类型只能修改该引用类型的属性而不能给该变量重新赋值(const确定了一个地址,该地址不能被修改)
    • let和const存在块级作用域,而var不存在
    • let在for循环中每循环一次就会重新声明一次(因为let有块级作用域)

    是不是感觉自己说得好全了,然而面试管总是喜欢坑人的,下面两个问题就是用来坑你的。

    为什么let和const不能重复声明?为什么let和const存在暂时性死区?

    这也太坑了吧,我TMD怎么知道。好了好了,别吐槽,我们现在就来解决这个问题。

     在ES6规范有一个词叫做Global Enviroment Records(也就是全局环境变量记录),它里面包含两个内容,一个是Object Enviroment Record,另一个是Reclarative Enviroment Record。函数声明和使用var声明的变量会添加进入Object Enviroment Record中,而使用let声明和使用const声明的变量会添加入Reclarative Enviroment Record中。下面是ECMAscript规范中对var,let,const的一些约束。

    也就是说:

    • 使用var声明时,V8引擎只会检查Declarative Enviroment Record中是否有该变量,如果有,就会报错,否则将该变量添加入Object Enviroment Record中。
    • 使用let和const声明时,引擎会同时检查Object Enviroment Record和Declarative Enviroment Record,如果有,则报错,否则将将变量添加入Declarative Enviroment Record中。

    这就解释了为什么使用var声明的变量可以重复声明,而是用let和const声明的变量不可以重复声明。

    那为什么会存在暂时性死区呢?

    首先我们来问一个问题,let和const声明的变量的声明真的没有提升吗?我们来做一个简单的测试。

    可以看到,我们使用Object.defineProperty在Object Enviroment Record中添加了一个变量a,当我们让let a和Object.defineProperty同时在一个代码块中时,没有报错,而当我们先执行Object.defineProperty后再用let声明a时,浏览器报错了。其实这里就已经说明了一个问题,我想聪明的你也一定想到了。那就是let声明被提升了,但是使用let声明的变量还没有初始化,它连一个undefined的值都没有,我们使用chrome浏览器来进一步测试:

    可以看到chrome中说在初始化前无法访问a。所以说,使用let和const声明的变量的声明提升了,但是没有初始化,连一个undefined的值都没有。

    这就是暂时性死区出现的原因。

    好了,你get到我说的内容了吗?希望本文章能帮助你更加深入理解var,let,const的区别。o(* ̄▽ ̄*)ブ!

    展开全文
  • let和const是 ES6 新增的命令,用于声明变量,这两个命令跟 ES5 的var有许多不同,并且let和const也有一些细微的不同 var和let/const的区别 块级作用域 不存在变量提升 暂时性死区 ...为什么需要块级.

    letconst是 ES6 新增的命令,用于声明变量,这两个命令跟 ES5 的var有许多不同,并且letconst也有一些细微的不同

    varlet/const的区别

    1. 块级作用域
    2. 不存在变量提升
    3. 暂时性死区
    4. 不可重复声明
    5. let、const声明的全局变量不会挂在顶层对象下面

    const命令两个注意点:

    1. const 声明之后必须马上赋值,否则会报错
    2. const 简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改。

    为什么需要块级作用域?

    ES5只有全局作用域和函数作用域,没有块级作用域。

    这带来很多不合理的场景:

    1. 内层变量可能覆盖外层变量
    2. 用来计数的循环变量泄露为全局变量
    var tmp = new Date();
    function f() {
      console.log(tmp); // 想打印外层的时间作用域
      if (false) {
        var tmp = 'hello world'; // 这里声明的作用域为整个函数
      }
    }
    f(); // undefined
    
    var s = 'hello';
    for (var i = 0; i < s.length; i++) {
      console.log(s[i]); // i应该为此次for循环使用的变量
    }
    console.log(i); // 5 全局范围都可以读到

    块级作用域

    1. 作用域
    function f1() {
      let n = 5;
      if (true) {
        let n = 10;
        console.log(n); // 10 内层的n
      }
      console.log(n); // 5 当前层的n
    }
    1. 块级作用域任意嵌套
    {{{{
      {let insane = 'Hello World'}
      console.log(insane); // 报错 读不到子作用域的变量
    }}}};
    1. 块级作用域真正使代码分割成块了
    {
    let a = ...;
    ...
    }
    {
    let a = ...;
    ...
    }

    以上形式,可以用于测试一些想法,不用担心变量重名,也不用担心外界干扰

    块级作用域声明函数:

    在块级作用域声明函数,因为浏览器的要兼容老代码,会产生一些问题!

    在块级作用域声明函数,最好使用匿名函数的形式

    if(true){
      let a = function () {}; // 作用域为块级 令声明的函数作用域范围更清晰
    }

    ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错

    // 报错
    'use strict';
    if (true)
      function f() {} // 我们需要给if加个{}

    不存在变量提升

    变量提升的现象:在同一作用域下,变量可以在声明之前使用,值为 undefined

    ES5 时使用var声明变量,经常会出现变量提升的现象。

    // var 的情况
    console.log(foo); // 输出undefined
    var foo = 2;
    
    // let 的情况
    console.log(bar); // 报错ReferenceError
    let bar = 2;

    暂时性死区:

    只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量

    var tmp = 123; // 声明
    if (true) {
      tmp = 'abc'; // 报错 因为本区域有tmp声明变量
      let tmp; // 绑定if这个块级的作用域 不能出现tmp变量
    }

    暂时性死区和不能变量提升的意义在于:

    为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。

    不允许重复声明变量

    在测试时出现这种情况:var a= '声明';const a = '不报错',这种情况是因为babel在转化的时候,做了一些处理,在浏览器的控制台中测试,就成功报错

    letconst不允许在相同作用域内,重复声明同一个变量

    function func(arg) {
      let arg; // 报错
    }
    
    function func(arg) {
      {
        let arg; // 不报错
      }
    }

    let、const声明的全局变量不会挂在顶层对象下面

    1. 浏览器环境顶层对象是: window
    2. node环境顶层对象是: global
    3. var声明的全局变量会挂在顶层对象下面,而let、const不会挂在顶层对象下面。如下面这个栗子
    var a = 1;
    // 如果在 Node环境,可以写成 global.a
    // 或者采用通用方法,写成 this.a
    window.a // 1
    
    let b = 1;
    window.b // undefined

    const命令

    1. 一旦声明,必须马上赋值

      let p; var p1; // 不报错
      const p3 = '马上赋值'
      const p3; // 报错 没有赋值
    2. const一旦声明值就不能改变

      简单类型:不能改动

      const p = '不能改变';
      p = '报错'

      复杂类型:变量指针不能变

      考虑如下情况:

      const p = ['不能改动']
      const p2 = {
        name: 'OBKoro1'
      }
      p[0] = '不报错'
      p2.name = '不报错'
      p = ['报错']
      p2 = {
        name: '报错'
      }

      const所说的一旦声明值就不能改变,实际上指的是:变量指向的那个内存地址所保存的数据不得改动

      • 简单类型(number、string、boolean):内存地址就是值,即常量(一变就报错).

      • 复杂类型(对象、数组等):地址保存的是一个指针,const只能保证指针是固定的(总是指向同一个地址),它内部的值是可以改变的(不要以为const就安全了!)

        所以只要不重新赋值整个数组/对象, 因为保存的是一个指针,所以对数组使用的pushshiftsplice等方法也是允许的,你就是把值一个一个全都删光了都不会报错。

      复杂类型还有函数,正则等,这点也要注意一下。

    总结:

    再总结一下,看到这些名词,脑子里应该会有对应的理解,如果没有的话,那可以再看看对应的内容。

    varlet/const的区别:

    1. 块级作用域
    2. 不存在变量提升
    3. 暂时性死区
    4. 不可重复声明
    5. let、const声明的全局变量不会挂在顶层对象下面

    const命令两个注意点:

    1. let可以先声明稍后再赋值,而const在 声明之后必须马上赋值,否则会报错

    2. const 简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改。

    let、const使用场景:

    1. let使用场景:变量,用以替代var
    2. const使用场景:常量、声明匿名函数、箭头函数的时候。
    展开全文
  • 什么是全局污染? function test () { web = 'hello world' } 这种不声明就直接赋值的变量就会直接成为全局变量,这...避免忘记使用,可以通过开启严格模式来强制提醒 "use strict"//直接扔到js里面就行 ...
    1. 什么是全局污染和重复声明?
    function test () {
    	web = 'hello world'
    }
    

    这种不声明就直接赋值的变量就会直接成为全局变量,这就是全局污染。
    而使用var来声明的变量也都会成为window的对象,这就是window的全局对象污染,要通过let,const来声明。
    重复声明就是使用var同一个变量名时不会报错,这样导致前面的变量被覆盖,而let,const会直接报错提示。
    2. 全局污染有什么问题?
    会导致有隐患,当在其他地方再次应用这个变量时,值就不好控制。
    3. 怎么解决全局污染?
    通过使用var ,let , const来声明变量,让私有变量不再是全局变量,
    为避免忘记使用,可以通过开启严格模式来强制提醒

    	"use strict"//直接扔到js里面就行
    

    严格模式只会管理当前作用域自身以下的,哪怕是当前作用域自身以上的都约束不了,所以直接扔在开头就行。

    展开全文
  • let var const详细区别

    2020-11-23 11:24:01
    是否允许重复声明变量4.是否存在块级作用域什么是块级作用域:5.是否能修改声明的变量 在ES5中,声明变量只有var和function两种形式。但是因为var声明的变量会有一定的缺点(内层变量可能覆盖外层变量的问题以及用来...
  • let、const和var的区别?

    2021-06-03 15:37:18
    在JavaScript中有三种定义变量的方式,分别 var let和const,他们之间有什么区别呢,跟着我一起学习吧! var 使用var声明的变量有变量提升,不会报错,会输出undefined 可以重复定义同一个变量 可以跨块访问 不能跨函数...
  • var、let与const的区别

    2020-12-26 16:49:48
    重复声明变量问题5.总结三.const1.定义2.块级作用域3.赋予初始值4.常量不可以修改5.总结四.区别 一.为什么使用ES6? 每一次标准的诞生都意味着语言的完善,功能的加强。JavaScript语言本身也有一些令人不满意的地方...
  • 可以重复声明; 无法限制修改,(有的常量是不需要改变的,但是var不能满足); 没有快级作用域; **变量可以被重复声明是其他语言所不接受的,(虽然我也没用过几种语言,但是相信我,这是真的…) **无法限制修改,...
  • 函数声明及调用初解

    2017-01-09 18:33:22
    执行时调用需要先声明可以重复使用。 声明方式:1、function fn(){} 2、var fn=function(){}; 3、 var fn=function fn1(){}; 4、var fn=new Function(); //fn自行取的函数名,但同时需要遵循命名规范。 调用...
  • 小米商城平台的法律声明、隐私政策、平台规范、规则、通知、公告、操作规则、帮助文档、温馨提示等均本协议的补充协议,与本协议不可分割且具有同等法律效力。如您使用本平台服务,视您同意上述补充...
  • ES6语法和应用

    2021-06-13 11:32:38
    1.var 可以重复声明 2.var无法限制修改 3.var 没有块级作用域 闭包主要为了解决什么问题?? 主要解决var没有块级作用域,只能用function做闭包处理。 <script> //var的缺点们 //重复声明
  • ES6新增let

    2021-04-20 10:43:08
    //var 不好用 1.var 可以重复声明 2.var 无法限制修改,var 没有块级作用域 //重复声明 var a=10 ; var a =20 ; /* 块级作用域:{} if(){} for(){} 只有在function(){} 中有作用域 */ var 作用域问题 <...
  • ES6,方法及笔记

    2019-11-20 20:13:02
    ES6 ES6的全称叫做ECMAScript或者ES2015 因为它是2015年出来的排行老六,所以怎么叫都是对的 为什么要用ES6 ...支持更多语法,使用更方便 ...var可以重复声明, 1) var 可以重复定义 2) let 不能重复定义 3) ...
  • ECMAScript6面试题

    2020-11-17 11:49:05
    var 全局作用域 可以重复声明 可以重复赋值 暂时性死区: 我个人理解,所谓的暂时性死区就是在会计作用域内使用let声明了变量,那么这个变量就不会受外部的影响,这个我把它理解暂时性死区。 变量提升: ...
  • ES6笔记

    2021-04-02 13:58:04
    var可以重复声明 b. var无法限制修改 c. var没有块级作用域 块级作用域:{}、if() {}、 for() {} 只有在function(){} 中有作用域 let 块级作用域 var name = "edu" if (true) { var name = "hei"; console.log...
  • var 作用域 函数作用域、有变量提升、可以重复声明、有暂时性死区 关于作用域 作用域:JS(ES6之前)作用域有 全局作用域 、函数作用域(局部作用域)。 ES6新增块级作用域。 全局作用域: 最外层函数和在最外层函数...
  • ES6基础语法

    2018-10-11 09:26:24
    为什么要用ES6??? 1.... 2.... 3....变量声明 ... 声明可以重复 2. 声明会提升 console.log(b); var b = 3; 3. 没有局部作用域 if(true){ var c = 3; } console.log(c); //c=...
  • 函数类型详解

    2019-05-29 00:47:33
    什么是函数? 可以反复执行的代码块,有独立作用域,我们称为函数。 函数有什么作用? 1.简化代码 2.封装功能 ...var fn = function(){} 字面量 ...**重复声明是会覆盖的 函数的参数 分为形参和实参 形...
  • ES6简单入门

    2020-04-06 11:26:57
    认识ES6 什么是ES6 ECAMScript是JavaScript的标准,JS是ES的实现;主流实现只有JS,所以很多时候JS就等同于ECMA 正式名称:ES2015,是ECMA标准的第6版 为什么使用ES6 语言都在更新换代,加入新...可以重复声明,可...
  • ES6的基本语法

    2020-08-06 15:35:13
    let属于块级作用域,不允许重复声明 const:声明常量,一旦声明立刻赋值 为什么需要块级 内层变量可能会覆盖外层变量 使用闭包来解决循环计数的问题 使用let解决循环计数 let可以被修改 const一旦声明...
  • 同时,var 变量提升,可重复声明的特点可能导致内部变量覆盖外部变量,引发意料外的错误。 var tmp = 1; function f() { console.log(tmp); if (false) { var tmp = 'test'; } } f(); // undefined
  • [JS学习笔记]Week1

    2021-01-04 11:38:50
    文章目录什么是JSECMAScript诞生背景怎么理解ECMAScript一个完整JS的组成关键词变量变量声明用let或var声明变量let和var的区别ES6可以用let定义块级作用域变量**let 配合for循环的独特应用**let没有变量提升与暂时性...
  • ES6学习笔记

    2018-02-01 11:44:20
    let 块级作用域,该语句所在的代码块内,不存在变量提升,暂时性死区,相同作用域不允许重复声明。 const 使用声明的常量(栈内存在的值和地址),值类型的不可以改,引用类型的可变,引用不可变要用Object.freeze...
  • day5 函数

    2019-12-22 18:48:18
    为什么要有函数 如果要在多个地方求1-100之间所有数的和,应该怎么做? 概念:当它被调用时执行的可重复使用的代码块。 什么是函数 函数的作用就是封装一段代码,将来可以重复使用。 就是函数,起个名字(函数名...
  • jsday4笔记

    2019-12-21 14:12:19
    为什么要有函数 如果要在多个地方求1-100之间所有数的和,应该怎么做? 概念:当它被调用时执行的可重复使用的代码块。 什么是函数 函数的作用就是封装一段代码,将来可以重复使用。 就是函数,起个名字(函数名...
  • 复习

    2019-12-22 18:46:58
    为什么要有函数 如果要在多个地方求1-100之间所有数的和,应该怎么做? 概念:当它被调用时执行的可重复使用的代码块。 什么是函数 函数的作用就是封装一段代码,将来可以重复使用。 就是函数,起个名字(函数名...
  • JavaScript函数的执行

    2020-10-29 23:35:20
    为什么要有函数? 如果要在多个地方求1-100之间所有数的和,应该怎么做? 什么是函数? 把一段相对独立的具有特定功能的代码块封装起来,形成一个独立实体,就是函数,起个名字(函数名),在后续开发中可以反复调用...
  • 函数:初涉

    2019-09-27 16:38:31
    为什么要使用函数 什么是函数 把一段相对独立的具有特定功能的代码块封装起来,形成一个独立实体,就是函数,起个名字(函数名),在后续开发中可以反复调用 提高代码复用性 函数的作用就是封装一段代码,将来可以...

空空如也

空空如也

1 2 3 4
收藏数 70
精华内容 28
关键字:

为什么var可以重复声明