[Day03] JavaScript - 变数宣告 var / let / const

此篇再延续上篇,详细纪录一下三种宣告方式的不同。
在ES6之前只有var的宣告方式;在ES6之後,即新增了let & const两种方式:

1.  var - 宣告一个可随意更改内容的变数 - 函式作用域 (function-level scope)

      ⇒ 只有在「函式」里可以看得到,特性相当於全域变数

  • 不会受限在区域(block scope)内,可能会污染全域变数。不管哪个作用域(Scope)都可以存取,可以重复宣告。(区域变数会覆盖全域变数)

    范例如下:

    var a = 5;
    if (true) {
        var a = 10;    //区域变数覆盖全域变数!!
        console.log(a);  //结果为10
    }
    console.log(a);  //结果为10   
    
  • 再看以下范例,若在一个 函式 内使用 var 宣告变数时,那这个变数就变成了一个区域变数,只有在函式内才看得到。

    var a = 5
    function MyFunction() {
      if (true) {
        var a = 10;
      }
      console.log(a); // 结果为10
    }
    
    MyFunction();
    console.log(a); // 结果为5
    

2.  let - 宣告一个可随意更改内容的区域变数-区块作用域 (block-level scope)

      ⇒ 只有在「区块」里面才看得到,即只有在 {}花括号 里的才是它的作用域范围。

  • 所宣告的变项只有在区域内(block scope)有效,不会产生全域变数,也就是 { } 包住的区域,一但离开 { } 范围,这个变数就不会被存取到,也无法在同一层 Block 重复宣告变数。

    var b = 6;
    if (true) {
        let b = 20;
        console.log(b);  //出现20
    }
    console.log(b);  //出现6 即为{}外的变数=6
    
    • 无法在同一层 Block 重复宣告变数:

      let a = 6;
      let a = 20;
      console.log(a);
      //出现错误:Identifier 'a' has already been declared**
      
    • 但是如果 let 宣告的变数在 不同层的Block ,就不会报错:

      let a = 6;
      
      if (true) {
      	let a = 20;
      	console.log(a);  //出现20
      }
      console.log(a);  //出现6
      

3.  const - 宣告一个只可读取的不可变常数-区块作用域 (block-level scope)

          ⇒ 只有在「区块」里面才看得到,即只有在 {}花括号 里的才是它的作用域范围。

  • 宣告後不能更改值,否则会报错

    const a = 123;
    a = 456;  // TypeError: Assignment to constant variable.
    
  • 一宣告时就必定要指定给值,否则会报错

    const b ;  
    b = 456;   //SyntaxError: Missing initializer in const declaration
    

宣告&不宣告的差异

  • 只要无宣告变数直接赋值就会被视为 全域变数
    (写在全域环境的 var、let、const 变数同样可以视为全域变数)

  • 另一点差异是 能不能透过 delet 操作删除变数 ,先来看下面程序码:

//未宣告
a = 6;
delete a;   //true
console.log(a);    //a is not defined

//宣告
var b = 10;
delete b;   //false
console.log(b);    //10;

从以上范例可以发现,有使用var宣告的b是不可被删除的,而未宣告的a可以被删除。

这是因为如果没有经过var宣告的变数「会被当作物件属性」的方式新增,因此才会强烈建议变数一定要宣告,否则可轻易被删除的变数是很容易出现出问题的。

我们可以透过Object.getOwnPropertyDescriptor来获取全域属性: (可参考MDN)

//未宣告
a = 6;
Object.getOwnPropertyDescriptor(window, 'a')
//{value: 6, writable: true, enumerable: true, configurable: true}

//宣告
var b = 10;
Object.getOwnPropertyDescriptor(window, 'b')    
//{value: 10, writable: true, enumerable: true, configurable: false}

由上方a, b 变数的属性可发现,两者的配置性configurable有所不同。而configurable为false的代表此物件属性无法被删除,configurable为true的则反之。

 因此,经过var宣告的变数是不能被delete的。

 
 
 

参考来源:
https://hsiangfeng.github.io/javascript/20200425/539985371/
https://ithelp.ithome.com.tw/articles/10191549
https://tw.alphacamp.co/blog/javascript-var-let-const


<<:  Day3 风生水起,观元辰宫的火

>>:  html清单

[Part 1 ] Vue.js 的精随-元件

前言 接下来多篇的元件介绍会以官方文件 Components In-Depth 章节为主: 未知pa...

802.1X 是网路访问控制 (NAC) 的 IEEE 标准

-802.1X 角色 .请求者不直接向 RADIUS 服务器进行身份验证。它向身份验证者进行身份验...

11.MYSQL 资料型态

在资料库当中的资料也一定某种型态的资料,SQL中要开一个新栏位也需要定义资料型态,所以下面帮大家整理...

【DAY 30】生命不该浪费在重复的琐事

哈罗大家好~ 不知不觉,这个系列就要来到尾声了,这30天,我们分享了 Microsoft 365 帮...

Day 20:会议

前言 除了开发新功能,开会占据了我们许多时间,如果能够节省时间出来,我们才能去学些新技术、重构、甚至...