let和const命令總結

let和const命令

let命令

基本用法

let用來聲明變量,但所聲明的變量只在let命令所在的代碼塊內有效,下面的代碼在let命令的代碼塊外引用a會報錯:

{
    let a = 10;
}
a // ReferenceError: a is not defined.

for循環(huán)適合用let命令

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

上面代碼中的i 是let聲明的,當前的i只在本輪有效,每一個循環(huán)的i都是一個新的變量。

注意:for循環(huán)的設置循環(huán)變量的部分是一個父作用域,而循環(huán)體內是一個單獨的子作用域

不存在變量提升

“變量提升”即變量可以在聲明之前使用,值為undefined。而let命令不存在變量提升,它所聲明的變量一定要在聲明之后使用,否則會報錯。

暫時性死區(qū)

只要塊級作用域內存在let命令,它所聲明的變量就綁定這個區(qū)域,不再受外部的影響

“暫時性死區(qū)”是指在代碼塊中,使用let聲明變量之前,變量都是不可用的,否則會報錯。

如果在變量使用let命令聲明之前,使用typeof操作符會報錯:

typeof x; // ReferenceError
let x;

但如果變量根本沒有被聲明,則不糊報錯:

typeof undeclared_variable // "undefined"

較隱蔽死區(qū):

  1. 下面代碼中,參數x的默認值等于y,但此時y還沒有聲明,會報錯

    function bar(x = y, y = 2) {
      return [x, y];
    }
    
    bar(); // 報錯
    
  2. 下面代碼中,使用let命令聲明變量時,變量還沒有聲明完成,會報錯

    // 不報錯
    var x = x;
    
    // 報錯
    let x = x;
    // ReferenceError: x is not defined
    

不允許重復聲明

let不允許在同一個作用域內重復聲明函數

// 報錯
function func() {
  let a = 10;
  var a = 1;
}

// 報錯
function func() {
  let a = 10;
  let a = 1;
}

因此不能再函數內部重新聲明參數

function func(arg) {
  let arg;
}
func() // 報錯

function func(arg) {
  {
    let arg;
  }
}
func() // 不報錯

塊級作用域

使用塊級作用域的原因

  1. 內層變量可能會覆蓋外層變量(因為存在變量提升)

  2. 用來計數的循環(huán)變量可能會泄露為全局變量

es6的塊級作用域

es6允許塊級作用域任意嵌套,外層作用域無法讀取內層作用域的變量,內層作用域可以定義外層作用域的同名變量

塊級作用域的出現,使立即執(zhí)行函數表達式(IIFE)不再必要。

// IIFE 寫法
(function () {
  var tmp = ...;
  ...
}());

// 塊級作用域寫法
{
  let tmp = ...;
  ...
}

塊級作用域與函數聲明

背景:ES5 規(guī)定,函數只能在頂層作用域和函數作用域之中聲明,不能在塊級作用域聲明。但瀏覽器沒有遵守這個規(guī)定。

es5中,在if內聲明是函數會被提到函數頭部,若執(zhí)行以下代碼:

(function () {
  if (false) {
    // 重復聲明一次函數f
    function f() { console.log('I am inside!'); }
  }
  f();
}());

那么實際執(zhí)行的是:

(function () {
  function f() { console.log('I am inside!'); }
  if (false) {
  }
  f();
}());

es6引入塊級作用域,允許在塊級代碼中聲明函數,函數在塊級作用域之外不可用.

以下三條規(guī)則只對es6的瀏覽器有用(其他環(huán)境將塊級作用域聲明的函數當做let命令處理):

  1. 允許在塊級作用域內聲明函數

  2. 函數聲明類似于var,會提升到全局做用域或函數作用域的頭部

  3. 函數聲明還會提升到所在塊級作用域的頭部

應該避免在塊級作用域聲明函數,如果需要,應寫成函數表達式,避免寫成函數聲明語句

// 函數聲明語句
{
  let a = 'secret';
  function f() {
    return a;
  }
}

// 函數表達式
{
  let a = 'secret';
  let f = function () {
    return a;
  };
}

注意:es6的塊級作用域允許聲明函數的規(guī)則只在使用大括號的情況下成立,否則會報錯。

const命令

基本用法

const聲明一個只讀常量,一旦聲明,常量的值不改變;且一旦聲明變量,必須立刻初始化,否則會報錯

作用域:只在所聲明的塊級作用域有效。

const命令聲明的常量也不提升,也存在暫時性死區(qū),也不可重復聲明

本質

const實際上是變量指向的內存地址固定。對于復合類型的數據(對象和數組),變量指向的內存地址保存的是指向數據的指針。且const只保證這個指針是固定的,對于數據結構可不可變無法控制

const foo = {};

// 為 foo 添加一個屬性,可以成功
foo.prop = 123;
foo.prop // 123

// 將 foo 指向另一個對象,就會報錯
foo = {}; // TypeError: "foo" is read-only

如果像凍結對象,用object.freeze方法

const foo = Object.freeze({});

// 常規(guī)模式時,下面一行不起作用;
// 嚴格模式時,該行會報錯
foo.prop = 123;

下面代碼將對象徹底凍結(對象的屬性也凍結):

var constantize = (obj) => {
  Object.freeze(obj);
  Object.keys(obj).forEach( (key, i) => {
    if ( typeof obj[key] === 'object' ) {
      constantize( obj[key] );
    }
  });
};

es6聲明變量的六種方法

var、functionlet、constimportclass

頂層對象的屬性

頂層對象:在瀏覽器中指window對象,在node指的是global對象。

在es6中,var和function命令聲明的全局變量,依舊是頂層對象的屬性;let、const、class命令生命的全局變量不是頂層對象的屬性:

var a = 1;
// 如果在 Node 的 REPL 環(huán)境,可以寫成 global.a
// 或者采用通用方法,寫成 this.a
window.a // 1

let b = 1;
window.b // undefined

global對象

this變量的局限性(背景):

  1. 全局環(huán)境中,this會返回頂層對象。但是,Node 模塊和 ES6 模塊中,this返回的是當前模塊。

  2. 函數里面的this,如果函數不是作為對象的方法運行,而是單純作為函數運行,this會指向頂層對象。但是,嚴格模式下,這時this會返回undefined。

  3. 不管是嚴格模式,還是普通模式,new Function('return this')(),總是會返回全局對象。

很難找到一種方法可以在所有情況下都取得頂層對象。有一個提案,在語言標準的層面,引入global作為頂層對象。也就是說,在所有環(huán)境下,global都是存在的,都可以從它拿到頂層對象。

墊片庫system.global模擬了這個提案,可以在所有環(huán)境拿到global,如下:

// CommonJS 的寫法
require('system.global/shim')();

// ES6 模塊的寫法
import shim from 'system.global/shim'; shim();

下面代碼將頂層對象放入變量global:

// CommonJS 的寫法
var global = require('system.global')();

// ES6 模塊的寫法
import getGlobal from 'system.global';
const global = getGlobal();

參考文獻

ECMAScript入門--阮一峰

?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • let 命令 塊級作用域 const 命令 頂層對象的屬性 global 對象 let 命令 基本用法 ES6 新...
    嘉奇呦_nice閱讀 1,695評論 0 2
  • let 命令 塊級作用域 const 命令 頂層對象的屬性 global 對象 let 命令 基本用法 ES6 新...
    卞卞村長L閱讀 683評論 0 0
  • let 和 const 命令 let 命令 塊級作用域 const 命令 頂層對象的屬性 gl...
    安小明閱讀 1,043評論 0 0
  • let 命令 1.基本用法 let 是ES6新增的命令,用于聲明變量。用法類似于var,但是聲明的變量只在let所...
    站在大神的肩膀上看世界閱讀 394評論 0 3
  • 前幾天看了戰(zhàn)友瀟瀟給我的信,真的是非常感動,這半月因各種事很容易上情緒,狀態(tài)一直不好。瀟瀟的來信讓我感受到被...
    不重復的昨天閱讀 154評論 0 0

友情鏈接更多精彩內容