ES6的新特性(一)

函数默认值

特性 & 语法

// Before
function decimal(num, fix) {
    fix = fix === void(0) ? 2 : fix;

    return +num.toFixed(fix);
}
// After
function decimal(num, fix = 2) {
    return +num.toFixed(fix);
}

首先,我们看一下之前我们是怎么写函数默认值的:我们通常会使用三元运算符来判断入参是否有值,然后决定是否使用默认值运行函数(如示例中 fix = fix === void(0) ? 2 : fix)

而在 ES6 中,我们可以直接在函数的显示入参中指定函数默认值(function decimal(num, fix = 2){}),很明显,这种写法更自然易懂,也更加方便,不过有一点需要注意:

设定了默认值的入参,应该放在没有设置默认值的参数之后,也就是我们不应该这样写:function decimal(fix = 2, num){},虽然通过变通手段也可以正常运行,但不符合规范。

模板字符串

特性 & 语法

// Before
// Before.1
var type = 'simple';
'This is a ' + type + ' string join.'

// Before.2
var type = 'multiline';
'This \nis \na \n' + type + '\nstring.'

// Before.3
var type = 'pretty singleline';
'This \
is \
a \
' + type + '\
string.'
// OR
// Before.4
'This ' +
'is' +
'a' +
type +
'string.'
// After
var type = 'singleline';
`This is a ${type} string.`

var type = 'multiline';
`This
is
a
${type}
string.`

var type = 'pretty singleline';
`This \
is \
a \
${type} \
string.`

我们之前在对字符串和变量进行拼接的时候,通常都是反复一段一段使用引号包裹的字符串,再反复使用加号进行拼接(Before.1)。多行字符串的时候我们还要写上蹩脚的 \n 来换行以得到一个多行的字符串(Before.2)。

在字符串过长的时候可能会使用 \ 在编辑器中书写多行字符串来表示单行字符串,用来方便较长的字符串在编辑器中的阅读(Before.3),或者简单粗暴的反复引号加号这样多行拼接(Before.4)。

ES6 中我们可以使用反引号(`,位于 TAB 上方)来输入一段简单明了的多行字符串,还可以在字符串中通过 ${变量名} 的形式方便地插入一个变量,是不是方便多了!

解构赋值

数组解构

var [a, ,b] = [1, 2, 3, 4, 5];
console.log(a); // => 1
console.log(b); // => 3

数组解构,使用变量声明关键字声明一个形参数组([a, , b]),等号后跟一个待解构目标数组([1, 2, 3]),解构时可以通过留空的方式跳过数组中间的个别元素,但是在形参数组中必须留有相应空位才可以继续解构之后的元素,如果要跳过的元素处于数组末端,则在形参数组中可以不予留空。

对象解构

var {b, c} = {a: 1, b: 2, c: 3};
console.log(b); // => 2
console.log(c); // => 3

对象解构与数组解构大体相同,不过需要注意一点

形参对象({b, c})的属性或方法名必须与待解构的目标对象中的属性或方法名完全相同才能解构到对应的属性或方法

对象匹配解构

var example = function() {
    return {a: 1, b: 2, c: 3};
}
var {a: d, b: e, c: f} = example();
console.log(d, e, f); // => 1, 2, 3

对象匹配解构是对象解构的一种延伸用法,我们可以在形参对象中使用:来更改解构后的变量名。

函数入参解构

function example({param: value}) {
    return value;
}
console.log(example({param: 5})); // => 5

函数的入参解构也是对象解构的一种延伸用法,我们可以通过改写入参对象目标值为变量名的方式,在函数内部直接获取到入参对象中某个属性或方法的值。

函数入参默认值解构

function example({x, y, z = 0}) {
    return x + y + z;
}
console.log(example({x: 1, y: 2}));       // => 3
console.log(example({x: 1, y: 2, z: 3})); // => 6

这是入参解构的另一种用法,我们可以在入参对象的形参属性或方法中使用等号的方式给入参对象的某些属性或方法设定默认值。

Let & Const

Let

无变量提升
// Before
console.log(num); // => undefined
var num = 1;
// After
console.log(num); // => ReferenceError
let num = 1;

使用 var 声明的变量会自动提升到当前作用域的顶部,如果声明位置与作用域顶部之间有另一个同名变量,很容易引起难以预知的错误。使用 let 声明的变量则不会进行变成提升,规避了这个隐患。

注意:var 声明的变量提升后虽然在声明语句之前输出为 undefined,但这并不代表 num 变量还没有被声明,此时 num 变量已经完成声明并分配了相应内存,只不过该变量目前的值为 undefined,并不是我们声明语句中赋的初始值 1。

有块级作用域

// Before
{
    var num = 1;

    console.log(num); // => 1
}
console.log(num);     // => 1
// After
{
    let num = 1;
    
    console.log(num); // => 1
}
console.log(num);     // => ReferenceError
  let 声明的变量只能在当前块级作用域中使用,最常见的应用大概就是 for(let i = 0, i < 10; i++) {},相信许多小伙伴在面试题中见过。

禁止重复声明
// Before
var dev = true;
var dev = false;

console.log(dev); // => false
// After
let dev = true;
let dev = false; // => SyntaxError

var 声明的变量可以重复声明,而且不会有任何警告或者提示,就这样悄悄的覆盖了一个值,隐患如变量提升一样让人担忧。( ̄┰ ̄*)

而 let 声明的变量如果进行重复声明,则会直接抛出一个语法错误(是的,就是直接明确地告诉你:你犯了一个相当低级的语法错误哦)

Const

无变量提升
有块级作用域
禁止重复声明

前 3 点跟 let 一个套路,就不多说了

禁止重复赋值

const DEV = true;
DEV = false; // => TypeError

基于静态常量的定义我们可以很明显知道,const 声明的常量一经声明便不能再更改其值,无需多说。

必须附初始值

const DEV; // => SyntaxError

也是基于定义,const 声明的常量既然一经声明便不能再更改其值,那声明的时候没有附初始值显然是不合理的,一个没有任何值的常量是没有意义的,浪费内存。

新增库函数
  ES6 新增了许多(相当多)的库函数,这里只介绍一些比较常用的。

题外话:多了解一下内建函数与方法有时候可以很方便高效地解决问题。有时候绞尽脑汁写好的一个算法,没准已经有内建函数实现了!而且内建函数经过四海八荒众神的考验,性能一定不错,哈哈。

Number

Number.EPSILON
Number.isInteger(Infinity); // => false
Number.isNaN('NaN');        // => false

首先是 ᶓ 这个常量属性,表示小数的极小值,主要用来判断浮点数计算是否精确,如果计算误差小于该阈值,则可以认为计算结果是正确的。

然后是 isInteger() 这个方法用来判断一个数是否为整数,返回布尔值。

最后是 isNaN() 用来判断入参是否为 NaN。是的,我们再也不用通过 NaN 不等于 NaN 才能确定一个 NaN 就是 NaN 这种反人类的逻辑来判断一个 NaN 值了!

if(NaN !== NaN) {
    console.log("Yes! This is actually the NaN!");
}```
  另外还有两个小改动:两个全局函数 parseInt() 与 parseFloat() 被移植到 Number 中,入参反参保持不变。这样所有数字处理相关的都在 Number 对象上嘞!规范多了。

String

'abcde'.includes('cd'); // => true
'abc'.repeat(3); // => 'abcabcabc'
'abc'.startsWith('a'); // => true
'abc'.endsWith('c'); // => true````

1、inclueds() 方法用来判断一个字符串中是否存在指定字符串
2、repeat() 方法用来重复一个字符串生成一个新的字符串
3、startsWith() 方法用来判断一个字符串是否以指定字符串开头,可以传入一个4、整数作为第二个参数,用来设置查找的起点,默认为 0,即从字符串第一位开始查找
5、endsWith() 与 startsWith() 方法相反

Array

Array.from(document.querySelectorAll('*')); // => returns a real array.
[0, 0, 0].fill(7, 1); // => [0, 7, 7]
[1, 2, 3].findIndex(function(x) {
    return x === 2;
}); // => 1
['a', 'b', 'c'].entries(); // => Iterator [0: 'a'], [1: 'b'], [2: 'c']
['a', 'b', 'c'].keys();    // => Iterator 0, 1, 2
['a', 'b', 'c'].values();  // => Iterator 'a', 'b', 'c'
// Before
new Array();        // => []
new Array(4);       // => [,,,]
new Array(4, 5, 6); // => [4, 5, 6]
// After
Array.of();         // => []
Array.of(4);        // => [4]
Array.of(4, 5, 6);  // => [4, 5, 6]
  ````
       首先是 from() 方法,该方法可以将一个类数组对象转换成一个真正的数组。还记得我们之前常写的 Array.prototype.slice.call(arguments) 吗?现在可以跟他说拜拜了~
  之后的 fill() 方法,用来填充一个数组,第一个参数为将要被填充到数组中的值,可选第二个参数为填充起始索引(默认为 0),可选第三参数为填充终止索引(默认填充到数组末端)。
      findIndex() 用来查找指定元素的索引值,入参为函数,函数形参跟 map() 方法一致,不多说。最终输出符合该条件的元素的索引值。
        entries()、keys()、values() 三个方法各自返回对应键值对、键、值的遍历器,可供循环结构使用。
  最后一个新增的 of() 方法主要是为了弥补 Array 当做构造函数使用时产生的怪异结果。
```
Object

let target = {
    a: 1,
    b: 3
};
let source = {
    b: 2,
    c: 3
};

Object.assign(target, source); // => { a: 1, b: 2, c: 3}

assign() 方法用于合并两个对象,不过需要注意的是这种合并是浅拷贝。可能看到这个方法我们还比较陌生,不过了解过 jQuery 源码的应该知道 $.extend() 这个方法,例如在下面这个粗糙的 $.ajax() 模型中的应用:

$.ajax = function(opts) {
    var defaultOpts = {
        method: 'GET',
        async: true,
        //...
    };
    opts = $.extend(defaultOpts, opts);
}```
  从这我们可以看到 TC39 也是在慢慢吸收百家所长,努力让 JavaScript 变得更好,更方便开发者的使用。

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

推荐阅读更多精彩内容