typescript let和const區別


全局聲明

var聲明在函數體外,所聲明的變量為全局變量。

var name = "張三";

var所聲明的全局變量會作為window的一個屬性,可以使用"."來引用。如上例的name引用:

console.log(window.name)

注意:非嚴格模式下,聲明在函數體內的變量,把聲明語句的var去掉,那么所聲明的變量也是全局變量。

作用域

var變量聲明的最大特點是它的作用域為聲明語句所在的最近函數體內。

示例:

function f() {
    var message = "Hello, world!";

    return message;
}

var所聲明的message變量的作用域范圍就是在函數f內。

var聲明變量的作用域為函數體的全部,隱含着兩個主要問題:變量提升和循環內變量共享。

變量提升

變量提升:JavaScript會把函數內的變量聲明提升到函數的最頂部。

示例:

function(){
    var a='a';
    var b='b';
    var c='c';
}

等同於

function(){
    var a,b,c;
    a='a';
    b='b';
    c='c';
}

這樣看是貌似沒有問題,想一下下面的例子輸出結果:

var message='message 1';
(function(){
    console.log(message)
    var message ='message 2';
})()

很多人可能會認為控制台輸出的結果是message 1。執行一下會發現,輸出的結果為undefined。這是因為變量提升了。

上面的例子實際等同於

var message='message 1';
(function(){
    var message;
    console.log(message)
    message ='message 2';
})()

變量提升有它的優勢,但也常常給我們帶來一些難以發現的bug。

循環內變量共享

直接看示例:

for (var i = 0; i < 10; i++) {
    setTimeout(function() { console.log(i); }, 100 * i);
}

我們期待的輸出結果為依次為0,1,2,3,4,5,6,7,8,9,而實際輸出結果都為10。這是因為在循環內共享了變量i,i自增到10結束setTimeOut()里的函數還沒有調用,當調用函數時,i值為10,所以輸出的結果都為10。

為了解決循環內變量共享,可以考慮使用IIFE。

for (var i = 0; i < 10; i++) {
    (function(i) {
        setTimeout(function() { console.log(i); }, 100 * i);
    })(i);
}

重復聲明

在上面的例子

var message='message 1';
(function(){
    console.log(message)
    var message ='message 2';
})()

message是允許重復聲明的,重復聲明的變量會覆蓋之前聲明的變量。

let變量聲明

let是ES6新增的特性,也是為了解決var變量聲明所存在的一些問題,可以說let是更完美的var。

基本用法

let varName = 變量值;

示例:

let name = "張三";

這是和var聲明變量類似。

注意:如果let變量聲明在全局,它並不會像var聲明的變量一樣成為window的一個屬性。

作用域

let變量聲明和var最大的不同點就是變量的作用域不一樣。var為函數作用域,而let變量聲明的為塊作用域(block-scoping)。

塊作用域會把聲明的變量限定在代碼塊(如使用{}括起來的代碼庫)或者for循環內,而不是整個函數體。

function f(input: boolean) {
    let a = 100;

    if (input) {
        let b = a + 1;
        return b;
    }
    // 出錯: 'b'屬於上面的代碼塊定義的,在代碼塊外不能使用。
    return b;
}

let聲明的變量不允許在聲明前使用,這樣解決了var變量提升引起的問題。

(function(){
  console.log(message);    //此處會報錯,Uncaught ReferenceError: message is not defined
  let message ='my message';
})()

對於循環內的變量,每次循環都會是捕獲值的副本作為運算,而不是共享同一個值,解決了var循環內共享變量的問題。所以前面for循環的例子只需把var改為let即可:

for (let i = 0; i < 10; i++) {
    setTimeout(function() { console.log(i); }, 100 * i);
}

重復聲明

let是不允許在同一作用域內重復聲明,重復聲明會報error: can't re-declare 'x' in the same scope。

function f(x) {
    let x = 100; // error: interferes with parameter declaration
}

function g() {
    let x = 100;
    var x = 100; // error: can't have both declarations of 'x'
}

const變量聲明

const變量聲明和let類似,但如它的名字所寓意,它定義的是常量,包含了兩層意思:

  1. 聲明的的變量不能被重復賦值
  2. const聲明變量是必須立刻賦值
const numLivesForCat = 9;
numLivesForCat = 10;  //重復賦值,錯誤

const name;  //錯誤,聲明時沒有賦值
name = "張三";  

對於const聲明的對象,對象本身是不能被賦值覆蓋,但是對象的可修改屬性是允許被修改值的。

const numLivesForCat = 9;
const kitty = {
    name: "Aurora",
    numLives: numLivesForCat,
}

// Error
kitty = {
    name: "Danielle",
    numLives: numLivesForCat
};

// all "okay"
kitty.name = "Rory";
kitty.name = "Kitty";
kitty.name = "Cat";
kitty.numLives--;

轉自:https://majing.io/posts/10000000721104


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM