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 ${b}` }`);     // 输出‘hello world’

如果声明多个变量:

let a = 'hello';
let b = 'world';
console.log(`${a `${b}`}`);     //报错:a is not a function(…),可见${}里面如果存在变量时,也不能放入另一个模板字符串。
(3)标签模板(tagged template)

定义一个test函数:

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

最后结果输出:



然而``调用函数和()调用函数还是有一定的区别,现在改成通过传参的方式调用函数:

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

结果输出的却是数组:



这就是模板字符串的‘标记模板’属性,所谓“标记模板”,就是定义一个函数,然后把该函数的函数名放在模板字符串的前面,这样就能将该函数和模板字符串联系起来,然后通过这个函数对模板字符串进行处理。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容