es6之聲明變量、解構賦值和模板字符串

一、聲明變量

es5之前,聲明變量只有var聲明、隱式聲明和函數聲明。而es6中則多了let和const。

(1)let和const的“塊級作用域”:
var  a = 1;
function test(){
   var a = 2; 
}
test();
console.log(a);

最終結果是"1",這是因為在js中,var有“函數作用域”,所以var a = 2的聲明只能在函數test區域里面有效,在外面則不會生效,現在去掉函數:

var a =1;
{
   var a = 2;
}
console.log(a);

得到的結果則是“2”,這是因為var沒有“塊級作用域”。
像c、java等其他語言中,變量的聲明都有“塊級作用域”,所謂“塊”,就是以花括號{}為邊界,而花括號里面的區域,就是這個聲明可以被訪問的域區,而花括號之外就不可以了。在es6中,新添加的let的const同樣擁有“塊級作用域”,將上面代碼中的var改成let:

let a = 1;
{
   let a = 2;
}
console.log(a);

最后輸出的結果依然是“1”,改成const也是這個結果。
塊級作用域,最大的應用,就是每篇let和const教學文章都會提到的for循環:

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

3次輸出的結果都是“2”;
而改用let:

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

則3次輸出的結果分別是“0、1、2”;

(2)var有提升變量的作用,而let和const則沒有。
console.log(a);
var a = 1;

則輸出的結果是:



因為var有提升變量的功能,但是不能提升賦值,所以輸出的結果就是undefined,上面的代碼就相當于:

var a;
console.log(a);
 a = 1;

如果把var改成let或者const,例如:

console.log(a);
let/const  a = 1;

則得到的結果就是:



造成這樣的原因,是因為在let和const聲明某個變量之前,會形成一個“Temporal Dead Zone”(暫時性死區),在這個區域里是無法訪問這個變量。

(3)var可以重復聲明,而let和const在同一塊級作用域中不可以:
(1)var a = 1;
          var a = 2;
(2)let a = 1;
          let a = 2;
(3)const a = 1;
          const a = 2;
(4)let a = 1;
          const a = 2;
(5)let a = 1;
          var a = 2;
(6)const a = 1;
          var a = 2;
console.log(a);

后面5種情況都會報錯:



[注意,let和const在不同塊級作用域則可以同時存在,參見(1)“塊級作用域部分”];

(4)const是常量不可變,let可變:

const的全拼“constant”就是不可變的意思

let a = 1;
a = a+1;
console.log(a);

輸出的結果是“2”,如果改成const:

const a = 1;
a = a +1;
console.log(a);

則會報錯:



需要注意的是,const的不可變并不是完全不可變,例如:

const  a =  [];
a.push(1);
console.log(a);

則輸出的結果是“[1]”,這是因為const更像是“constant reference”。
也就是說,地址不能改變,而地址指向的值可以改變。

二、解構賦值(Destructuring):

es6之前,變量聲明的結構是十分固定的,變量名放在等號的左邊,而數組[]、對象{}和字符串則是放在等號的右邊。而在es6中,它們的位置可以互相調換了。

let arr = [1,2,3];
let first = arr[0];
console.log(first);

則輸出的結果是‘1’。

let arr = [1,2,3];
let [first] = arr;
console.log(first);

則輸出的結果還是‘1’。
而對象的解構,屬性名與變量名需要保持一致,否則會輸出undefined

let {first}={'a':1};
console.log(first);  //undefined;

左側的變量可以通過逗號的形式跳過右側對應的值:

var [,b] = [1,2,3];
console.log(b);   // 輸出結果為‘2’;

解構賦值的優勢,就是能省去不少額外的聲明,最典型的應用,就是json,例如后臺通過ajax傳過來的數據都是json,那是用的時候就不需要一個屬性一個屬性的聲明了:

let json = {'username':xxx, 'option':'a', 'score':'100'}
let {username, option, score} = json;
console.log(username);
// 不用解構的話,想獲取json中username的值,就要寫成 json.username。

還有一個就是給函數的參數設定默認值:

function test(a,b){
    if(a == true){
        var b = 1;
    }else{
        var b = 2;
    }
    console.log(b);
}
test(false);

而使用解構賦值的話:

function test(a,{b = 2}){
    if(a == true){
        var b = 1;
    }
    console.log(b);
}
test(true,{});

另外要注意一點,解構賦值只能獲取值,不能改變值:

let json = {num:1, num2:2};
let { num2 } = json;
console.log(num2 );   // 輸出的結果為2;

num2 = 3;
console.log( json)  //  輸出的結果為{num:1, num2:2},而不是{num:1, num2:3};

通過解構賦值,json里num2的值被賦給了num2。但是反過來,如果你想通過直接修改num2的值來修改json里num2的值,這樣是不行的。
所以有時你可能還要再包一層json:

let json = { nums : { num:1 ,num2:2} };
let {nums} = json;

nums.num2 = 3;
console.log(json)  // 輸出結果為{nums : { num:1 ,num2:3} };

三、模板字符串(template strings)----字符串拼接:

es5之前字符串的拼接是通過把字符串放在雙引號或單引號里,而變量則通過‘+’和字符串拼接起來,而在es6中則是把字符串放在反引號`` 里,變量則放在$符號和花括號里,例如:

const word = "world";
console.log(`hi! ${word}.`);

輸出的結果為:



而這個${}被稱為“模板替換”(template substitutions),在這里你可以放任意JavaScript表達式(運算表達式,函數的調用)或者是某個對象屬性、另一個模板字符串。

(1)換行

模板字符串添加了一個新的功能,支持換行。把兩句話放在一個雙引號或者單引號里,在兩句話之間通按回車鍵進行換行,即:

console.log('this is line1,
this is line2');

js會認為這句話少了半邊引號,導致報錯,要想實現換行,只能在兩句話之間加轉移字符‘\n’。
如果換用反引號,即:



這樣是不會報錯的,只是輸出的結果則為:



這是因為第二句話并不是在第二行最開始的地方書寫,而是留有一定的空隙。由于模板字符串會保留反引號之內每一行的所有空格,所以導致這些空隙也被保留了下了。如果改成:

那么兩句話的開頭就是對齊的。

當然,如果你想要實現在html里換行,模板字符串里直接回車也是不會生效的,只有加上換行標簽</br>才行。

document.write(`this is line1,
</br>this is line2`)
(2)嵌套

提到模板字符串,大部分的文章都會提到類似“模板字符串之間還可以進行嵌套”之類的話,而這個嵌套,也主要是指在${}里放入另一個模板字符串。例如聲明一個變量:

let b = 'world';
console.log(``${a}``);                // 報錯,可見模板字符串不能直接嵌套在另一個反引號里。
console.log(`${ `hello $` }`);     // 輸出‘hello world’

如果聲明多個變量:

let a = 'hello';
let b = 'world';
console.log(`${a `$`}`);     //報錯:a is not a function(…),可見${}里面如果存在變量時,也不能放入另一個模板字符串。
(3)標簽模板(tagged template)

定義一個test函數:

function test(){
    console.log('hello');
};
test ``;

最后結果輸出:



然而``調用函數和()調用函數還是有一定的區別,現在改成通過傳參的方式調用函數:

function test(data){
    console.log(data);
};
test `hello`;

結果輸出的卻是數組:



這就是模板字符串的‘標記模板’屬性,所謂“標記模板”,就是定義一個函數,然后把該函數的函數名放在模板字符串的前面,這樣就能將該函數和模板字符串聯系起來,然后通過這個函數對模板字符串進行處理。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,182評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,489評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,290評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,776評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,510評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,866評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,860評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,036評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,585評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,331評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,536評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,058評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,754評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,154評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,469評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,273評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,505評論 2 379

推薦閱讀更多精彩內容