ES6

let和const

**ES5有兩種定義變量的方法:var和function糊识。ES6一共有6中聲明變量的方法:var,function,let,const以及import和class **

let

  1. 基本語法
1. let聲明變量只在其所在的代碼塊內(nèi)有效
{
    let a = 10;
    var b = 1;
}

a // 報錯席揽,ReferenceError: a is not defined
b // 1 

2. for循環(huán)中用let定義的變量只在循環(huán)體內(nèi)有效摆舟,在循環(huán)體外就無法使用到逊,和var不同用狱。并且for()中設(shè)置循環(huán)變量的是一個父作用域贴膘,而
循環(huán)體內(nèi)是另外一個單獨的作用域译仗。
for(let i = 0; i < 3;++i){
    let i = 'abc';
    console.log(i)
}
輸出:
abc abc abc   //可見是兩個單獨的作用域

3. 不允許重復(fù)聲明變量  let不允許在相同作用域內(nèi),重復(fù)聲明一個變量
function(){
    let a = 10;
    var a = 1;  //報錯 
}

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

//因此不能在函數(shù)內(nèi)部用let重新聲明參數(shù)
function func(arg) {
  let arg; // 報錯
}

function func(arg) {
 {
    let arg; // 不報錯
 } 
}
  1. 不存在變量提升
var定義變量會產(chǎn)生變量提升的現(xiàn)象抬虽,即變量可以在聲明之前使用,值為undefined纵菌。而let定義的變量阐污,一定要在聲明之后使用,否則就會報錯咱圆。
console.log(foo); //輸出undefined
var foo = 2;

console.log(bar);  //let變量聲明之前使用,會報錯ReferenceError
let bar = 2;
  1. 暫時性死區(qū)(TDZ)
  • 如果區(qū)塊中存在let和const命令笛辟,這個區(qū)塊中l(wèi)et和const聲明的變量,從一開始就形成了封閉作用域(塊級作用域),凡是在聲明之前使用
    這些變量,都會報錯闷堡。即為暫時性死區(qū)
1. var tmp = 123;
if(true){
    tmp = 'abc'; //報錯隘膘,ReferenceError
    let tmp;
}
// 上面代碼中,存在全局變量tmp,但是塊級作用域內(nèi)let又聲明了一個局部變量tmp,導(dǎo)致后者綁定這個塊級作用域杠览,所以在let聲明之前使用
對tmp賦值就會報錯弯菊。

有了暫時性死區(qū)的存在,也即意味著typeof會報錯
typeof x  //x 被let定義,這樣使用typeof就會報錯管钳,ReferenceError钦铁。如果沒有用let聲明,typeof會顯示undefined
let x 

2. 有一些死區(qū)比較隱蔽
function bar(x = y, y = 2){
    return [x,y]
}
bar()  //會報錯才漆,因為y還未聲明

function bar(x = 2, y = x){
    return [x,y]
}
bar()  //此時不會報錯牛曹,因為x已聲明

3. 下面這樣也會報錯
var x = x ;  //不報錯

let x = x ;  //報錯, x is not defined醇滥。因為x在未聲明之前使用

總之黎比,暫時性死區(qū)的本質(zhì)就是,只要一進入當(dāng)前作用域鸳玩,所要使用的變量就已經(jīng)存在了阅虫,但是不可獲取,只有等到聲明變量的那一行代碼出現(xiàn)不跟,才可以獲取和使用該變量颓帝。
  1. let實際上為JS新增了塊級作用域
1. function f1(){
    let n = 5;
    if(true){
        let n = 10;
    }
    console.log(n)  //5 
    //如果兩次都用var,會輸出10
}

2. ES6允許塊級作用域的任意嵌套
{{{{
  {let insane = 'Hello World'}
  console.log(insane); // 報錯
}}}};

內(nèi)層作用域可以定義外層作用域的同名變量。
{{{{
  let insane = 'Hello World';
  {let insane = 'Hello World'}
}}}};

const 聲明一個只讀的常量窝革,一旦聲明购城,值就不能改變

  1. const變量聲明時就必須立即初始化,且不能重新賦值
  2. const變量和let變量一樣,無變量提升,有塊級作用域虐译,不能重復(fù)聲明
  3. const定義對象或數(shù)組時瘪板,只是變量的指向的地址不能改變,而對象可以添加修改屬性
const foo = {};

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

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


const a = [];
a.push('Hello'); // 可執(zhí)行
a.length = 0;    // 可執(zhí)行
a = ['Dave'];    // 報錯 

如果想凍結(jié)對象,可以使用Object.freeze
const foo = Object.freeze({});  //foo指向一個被凍結(jié)的對象,所以不能添加屬性
// 常規(guī)模式時史侣,下面一行不起作用拴泌;
// 嚴格模式時,該行會報錯
foo.prop = 123; 

解構(gòu)賦值 從數(shù)組和對象中提取值惊橱,對變量進行賦值

  1. 數(shù)組解構(gòu)賦值
1. 
//這種寫法屬于模式匹配蚪腐,只要等號兩邊的模式相同,左邊的變量就會被賦予對應(yīng)的值
let [a,b,c] = [1,2,3]

//一些例子
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3

let [ , , third] = ["foo", "bar", "baz"];
third // "baz"

let [x, , y] = [1, 2, 3];
x // 1
y // 3

let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]

let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []

2. 如果解構(gòu)不成功税朴,變量的值就等于undefined
let [foo] = []  //foo的值為undefined
let [bar,foo] = [1]  //foo的值也為undefined

3. 不完全解構(gòu)回季,即等號左邊的模式 只匹配一部分的等號右邊的數(shù)組
let [x,y] = [1,2,3] // x = 1 ,y = 2 

let [a,[b],d] = [1,[2,3],4]  //a=1,b=2,d=4

4. 如果等號右邊的不是可遍歷的結(jié)構(gòu),就會報錯
// 報錯
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
//上面幾個表達式正林,前5個等號右邊轉(zhuǎn)換為對象后不具備Iterator接口泡一,最后一個本身不具備Iterator接口
只要某種數(shù)據(jù)結(jié)構(gòu)具有Iterator接口,都可以采用數(shù)組形式的解構(gòu)賦值觅廓,比如Set
let[x,y,z] = new Set(['a','b','c']); //x = 'a' 
  1. 默認值 解構(gòu)賦值允許指定默認值
1. 
let [foo=true] =[]  //foo=true 
let [x,y='b'] = ['a']  //x='a',y='b'
let [x,y='b'] = ['a',undefined] //x='a',y='b'

2. ES6使用嚴格相等運算符(===)判斷一個位置是否有值鼻忠,所以一個位置上不嚴格等于undefined,默認值不會生效
let [x=1] = [undefined]  //默認值生效,x=1 
let [x=1] = [null]  //默認值不生效杈绸,因為null不嚴格等于undefined帖蔓,x=null 

3. 默認值可以引用解構(gòu)賦值的其他變量矮瘟,但是該變量必須已經(jīng)申明
let [x=1,y=x] = [];  //x=1,y=1 
let [x=1,y=x] =[];   //x=1,y=2
let [x=1,y=x] =[1,2] //x=1,y=2
let [x=y,y=1] = [];  //報錯,因為x=y時塑娇,y還沒有聲明
  1. 對象的解構(gòu)賦值
1. 對象的解構(gòu)與數(shù)組的不同是澈侠,數(shù)組的元素必須是按次序排列的,變量的取值由它的位置決定埋酬;而對象的屬性與次序無關(guān)哨啃,變量必須與屬性
同名,才能取得正確的值写妥。
let { bar, foo } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"

let { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined

2. 如果變量名與屬性名不一致棘催,必須寫成下面形式
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'

let { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"
foo // error: foo is not defined  

這實際上說明,對象的解構(gòu)賦值是下面形式的簡寫(參見《對象的擴展》)
let { foo耳标,bar } = { foo: "aaa", bar: "bbb" }等同于下面
let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };
====================================================================
//foo: foo  冒號左邊是要與等號右邊匹配的模式(屬性)醇坝,冒號右邊才是要被賦值的變量 ,如果匹配不上次坡,變量的值就為undefined
=====================================================================

也就是說呼猪,對象解構(gòu)的內(nèi)部機制是先找到同名屬性,然后在賦值給對應(yīng)的變量的值砸琅。真正被賦值的是后者宋距,而不是前者
所以上面第二個例子,baz有值症脂,foo無值谚赎。foo是匹配的模式,baz才是變量诱篷,真正被賦值的是baz壶唤。

3. 對象解構(gòu)也可以嵌套
let obj = {
    p:[
     'hello',
      {y:'world'}
    ]
};

let {p:[x,{y}]} = obj;  //x='hello',y='world'
此時p是模式琳省,不是變量蔫巩,因此不會被賦值

若想P也作為變量賦值,可以寫成:
let obj = {
    p:[
     'hello',
      {y:'world'}
    ]
};

let {p,p:[x,{y}]} = obj; //x='hello',y='world',p = ["Hello", {y: "World"}]
再比如:
var node = {
  loc: {
    start: {
      line: 1,
      column: 5
    }
  }
};

var { loc, loc: { start }, loc: { start: { line }} } = node;
line // 1
loc  // Object {start: Object}
start // Object {line: 1, column: 5}

上面代碼只有三次解構(gòu)賦值截粗,分別是對loc,start,line三個屬性的解構(gòu)賦值菊值。最后一次對line屬性的解構(gòu)賦值儿子,只有l(wèi)ine是變量,
loc和start都是模式扑媚,不是變量

還可以這樣嵌套賦值
let obj = {};
let arr = [];

({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });

obj // {prop:123}
arr // [true]

4. 對象的解構(gòu)也可以指定默認值,默認值生效的條件也是對象的屬性值嚴格等于undefined
var {x=3} ={}  //x=3;
var {x,y=5} ={x:1} //x=1,y=5
var {x:y=3} ={}  //y=3;
var {x:y=3} = {x:5} //y=5

var { message: msg = 'Something went wrong' } = {};
msg // "Something went wrong"

var {x=3} = {x:undefined}  //x=3;
var {x=3} = {x:null}; //x=null 

如果解構(gòu)失敗人弓,變量的值等于undefined
let {foo} = {bar: 'baz'};
foo // undefined

5. 如果解構(gòu)模式是嵌套的對象,而且子對象所在的父屬性不存在痒留,那么將會報錯。

// 報錯
let {foo: {bar}} = {baz: 'baz'};
上面代碼中代乃,等號左邊對象的foo屬性仿粹,對應(yīng)一個子對象搁吓。該子對象的bar屬性,解構(gòu)時會報錯。原因很簡單,因為foo這時等于undefined蔑祟,再取子屬性就會報錯。

6. 如果要將一個已經(jīng)聲明的變量用于解構(gòu)賦值摩骨,必須非常小心通贞。

// 錯誤的寫法
let x;
{x} = {x: 1};
// SyntaxError: syntax error
上面代碼的寫法會報錯,因為 JavaScript 引擎會將{x}理解成一個代碼塊恼五,從而發(fā)生語法錯誤昌罩。只有不將大括號寫在行首,避免 JavaScript 將其解釋為代碼塊灾馒,才能解決這個問題峡迷。

// 正確的寫法
let x;
({x} = {x: 1});

7. 對象的解構(gòu)賦值,可以很方便的將現(xiàn)有對象的方法你虹,賦值到某個變量
let { log, sin, cos } = Math;
上面代碼將Math對象的對數(shù)绘搞、正弦、余弦三個方法傅物,賦值到對應(yīng)的變量上夯辖,使用起來就會方便很多。

8. 由于數(shù)組本質(zhì)是特殊的對象董饰,因此可以對數(shù)組進行對象屬性的解構(gòu)蒿褂。

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3
上面代碼對數(shù)組進行對象解構(gòu)。數(shù)組arr的0鍵對應(yīng)的值是1卒暂,[arr.length - 1]就是2鍵啄栓,對應(yīng)的值是3。方括號這種寫法也祠,屬于“屬性名表達式”昙楚,參見對象的擴展。
  1. 字符串的解構(gòu)賦值
字符串也可以解構(gòu)賦值诈嘿。這是因為此時堪旧,字符串被轉(zhuǎn)換成了一個類似數(shù)組的對象。

const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
類似數(shù)組的對象都有一個length屬性奖亚,因此還可以對這個屬性解構(gòu)賦值淳梦。

let {length : len} = 'hello';
len // 5
  1. 數(shù)值和布爾值的解構(gòu)賦值
解構(gòu)賦值時,如果等號右邊是數(shù)值和布爾值昔字,則會先轉(zhuǎn)為對象爆袍。

let {toString: s} = 123;
s === Number.prototype.toString // true

let {toString: s} = true;
s === Boolean.prototype.toString // true
上面代碼中,數(shù)值和布爾值的包裝對象都有toString屬性作郭,因此變量s都能取到值

解構(gòu)賦值的規(guī)則是陨囊,只要等號右邊的值不是對象或數(shù)組,就先將其轉(zhuǎn)為對象所坯。由于undefined和null無法轉(zhuǎn)為對象谆扎,所以對它們進行解構(gòu)賦值,都會報錯芹助。

let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError
  1. 函數(shù)參數(shù)的解構(gòu)賦值
1. function add([x,y]){
    return x + y;
}
add([1,2]) //3 
上面代碼中堂湖,函數(shù)add的參數(shù)表面上是一個數(shù)組,但在傳入?yún)?shù)的那一刻状土,數(shù)組參數(shù)就被解構(gòu)成變量x和y无蜂。對于函數(shù)內(nèi)部的代碼來說,它們能感受到的參數(shù)就是x和y蒙谓。

function g({name: x}) {
  console.log(x); //5 
}
g({name: 5})

再比如:
[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]

再如:
let cat ={
            run:function(){
                console.log('Running');
            }
         };

 function test({run}){
        run();
 }

test(cat); //傳入含有run屬性的對象即可

2. 函數(shù)參數(shù)的解構(gòu)也可以使用默認值斥季。

function move({x = 0, y = 0} = {}) {
  return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]

上面代碼中,函數(shù)move的參數(shù)是一個對象累驮,即等號右邊的{}酣倾,通過對這個對象進行解構(gòu),得到變量x和y的值谤专。如果解構(gòu)失敗躁锡,x和y等于默認值。

下面是和上面不同的情況:
function move({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
move(undefined);//[0,0]
上面代碼是為函數(shù)move的參數(shù)指定默認值置侍,而不是為變量x和y指定默認值映之,所以會得到與前一種寫法不同的結(jié)果。

undefined就會觸發(fā)函數(shù)參數(shù)的默認值蜡坊。
[1, undefined, 3].map((x = 'yes') => x);
// [ 1, 'yes', 3 ]

  1. 用途
1. 交換變量值
let x  =  1;
let y = 2;
[x,y] = [y,x]


2. 從函數(shù)返回多個值杠输,不用將它們放進一個數(shù)組或者對象了
//返回一個數(shù)組
function example(){
    return [1,2,3];
}

let [a,b,c] = example();

//返回一個對象
function example(){
    return {
        foo:2,
        bar:2
    };
}

let {foo,bar} = example();

3. 函數(shù)參數(shù)定義
解構(gòu)賦值可以方便地將一組參數(shù)與變量名對應(yīng)起來秕衙。

// 參數(shù)是一組有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);

// 參數(shù)是一組無次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});

4. 提取JSON數(shù)據(jù)
解構(gòu)賦值對提取JSON對象中的數(shù)據(jù)蠢甲,尤其有用。

let jsonData = {
  id: 42,
  status: "OK",
  data: [867, 5309]
};

let { id, status, data: number } = jsonData;

console.log(id, status, number);
// 42, "OK", [867, 5309]

5. 函數(shù)參數(shù)默認值
jQuery.ajax = function (url, {
  async = true,
  beforeSend = function () {},
  cache = true,
  complete = function () {},
  crossDomain = false,
  global = true,
  // ... more config
}) {
  // ... do stuff
};
指定參數(shù)的默認值据忘,就避免了在函數(shù)體內(nèi)部再寫var foo = config.foo || 'default foo';這樣的語句峡钓。

6. 遍歷Map結(jié)構(gòu)

任何部署了Iterator接口的對象,都可以用forof循環(huán)遍歷若河。Map結(jié)構(gòu)原生支持Iterator接口能岩,配合變量的解構(gòu)賦值,獲取鍵名和鍵值就非常方便萧福。

var map = new Map();
map.set('first', 'hello');
map.set('second', 'world');

for (let [key, value] of map) {
  console.log(key + " is " + value);
}
// first is hello
// second is world
如果只想獲取鍵名拉鹃,或者只想獲取鍵值,可以寫成下面這樣鲫忍。

// 獲取鍵名
for (let [key] of map) {
  // ...
}

// 獲取鍵值
for (let [,value] of map) {
  // ...
}

7.輸入模塊的指定方法

加載模塊時膏燕,往往需要指定輸入哪些方法。解構(gòu)賦值使得輸入語句非常清晰悟民。

const { SourceMapConsumer, SourceNode } = require("source-map");

字符串?dāng)U展

  1. 模板字符串
  • 模板字符串是增強版的字符串坝辫,用反引號(`)標(biāo)識,可以當(dāng)做普通字符串使用,也可以用來定義多行字符串射亏,或者在字符串中嵌入變量
// 普通字符串
`In JavaScript '\n' is a line-feed.`

// 多行字符串
`In JavaScript this is
 not legal.`

console.log(`string text line 1
string text line 2`);

// 字符串中嵌入變量
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

如果在模板字符串中需要使用反引號近忙,則前面要用反斜杠轉(zhuǎn)義竭业。
var greeting = `\`Yo\` World!`;

如果使用模板字符串表示多行字符串,所有的空格和縮進都會被保留在輸出之中及舍∥戳荆可以使用trim()去除。

模板字符串中嵌入變量锯玛,需要將變量名寫在${}之中,如果模板字符串中的變量沒有聲明咐柜,將報錯變量未聲明

花括號內(nèi)部可以放入任意的JS表達式,可以進行計算攘残,以及可以引用對象
var x = 1,y=2

`${x} + ${y} = ${x+y}`  //1+2=3

`${x} + ${y * 2} = ${x + y * 2}`  // "1 + 4 = 5"

var obj ={x:1,y:2}
`${obj.x + obj.y}`  //3 

模板字符串還能調(diào)用函數(shù)
function fn(){
    return 'Hello'
}
`foo ${fn()} bar`  //foo Hello World bar 

如果大括號中的值不是字符串拙友,將按照一般的規(guī)則轉(zhuǎn)為字符串。比如歼郭,大括號中是一個對象遗契,將默認調(diào)用對象的toString方法。

如果大括號中的變量未申明实撒,則會報錯姊途。

由于模板字符串的大括號內(nèi)部,就是執(zhí)行JavaScript代碼知态,因此如果大括號內(nèi)部是一個字符串捷兰,將會原樣輸出。

`Hello ${'World'}`
// "Hello World"

模版字符串也可以嵌套负敏。

函數(shù)擴展

  1. 函數(shù)參數(shù)的默認值
1. ES5中為函數(shù)參數(shù)設(shè)置默認值的方法:
function log(x,y){
    y = y || 'world';
    console.log(x,y)
}

log('hello')  //hello world
log('hello','china')  //hello china 
log('hello','')  //hello world 
上面寫法的缺點是贡茅,y賦值了,但是對應(yīng)的bool值為false,則y還是取world其做。所以還需要判斷參數(shù)y時否為賦值顶考,如果沒有再等于默認值
if(typeof y === 'undefined'){
    y = 'world'
}
而ES6中可以設(shè)置默認值
function log(x, y = 'World') {
  console.log(x, y);
}

log('Hello') // Hello World
log('Hello', 'China') // Hello China
log('Hello', '') // Hello

2. 參數(shù)變量是默認聲明的,所以不能用let或const再次聲明

3. 使用參數(shù)默認值時妖泄,函數(shù)名不能有同名參數(shù)
// 不報錯
function foo(x, x, y) {
  // ...
}

// 報錯
function foo(x, x, y = 1) {
  // ...
}

4. 另外驹沿,一個容易忽略的地方是,參數(shù)默認值不是傳值的蹈胡,而是每次都重新計算默認值表達式的值渊季。也就是說,參數(shù)默認值是惰性求值的罚渐。
let x = 99;
function foo(p = x + 1) {
  console.log(p);
}

foo() // 100

x = 100;
foo() // 101

上面代碼中却汉,參數(shù)p的默認值是x + 1。這時荷并,每次調(diào)用函數(shù)foo合砂,都會重新計算x + 1,而不是默認p等于 100源织。

  1. 與解構(gòu)賦值默認值結(jié)合使用
1. function foo({x,y=5}){
    console.log(x,y)
}
foo({}) // undefined 5 
foo({x:1}) //1 5 
foo({x:1,y:2})  //1,2
foo() //TypeError: Cannot read property 'x' of undefined 

上面只是使用了對象的解構(gòu)賦值默認值翩伪,沒有使用函數(shù)參數(shù)的默認值微猖。只有當(dāng)函數(shù)foo的參數(shù)是一個對象時,變量x和y才會通過解構(gòu)賦值生成幻工。如果函數(shù)foo調(diào)用時沒有提供參數(shù)励两,變量x和y就不會生成黎茎,從而報錯囊颅。通過設(shè)置函數(shù)參數(shù)的默認值,就可以避免這種情況

function foo({x,y=5} = {}){
    consoel.log(x,y)
}
foo() //undefined 5 
上面的定義傅瞻,如果沒有給函數(shù)傳參數(shù)踢代,函數(shù)foo的默認參數(shù)就是一個空對象({})

2. 解構(gòu)默認值與參數(shù)默認值結(jié)合
function fetch(url, { body = '', method = 'GET', headers = {} }) {
  console.log(method);
}

fetch('http://example.com', {})
// "GET"

fetch('http://example.com')
// 報錯

上面代碼中,函數(shù)fetch第二個參數(shù)是一個對象嗅骄,如果傳入一個對象就可以為它的三個屬性設(shè)置默認值胳挎。而省略第二個參數(shù)就會報錯。
結(jié)合函數(shù)參數(shù)默認值溺森,就可以省略第二個參數(shù)了慕爬。就設(shè)置了雙重默認值。
function fetch(url,{method = 'GET'} = {}){
    console.log(method)
}
fetch('http://example.com')
// "GET"

上面代碼中屏积,參數(shù)fetch沒有第二個參數(shù)時医窿,函數(shù)參數(shù)的默認值就是一個空對象,然后才是解構(gòu)賦值的默認值生效炊林。變量method才會取到默認值GET姥卢。

于是就有了下面兩種寫法:
//寫法1
function m1({x=0,y=0} = {}){
    return [x,y]
}
//寫法2 
function m2({x,y} = {x:0,y:0}){
    return [x,y]
}

上面的代碼,寫法1設(shè)置了函數(shù)參數(shù)的默認值是一個空對象渣聚,但是設(shè)置了對象解構(gòu)賦值的默認值
寫法2函數(shù)參數(shù)的默認值是一個有具體屬性的對象独榴,但是沒有設(shè)置對象解構(gòu)賦值的默認值。
// 函數(shù)沒有參數(shù)的情況
m1() // [0, 0]
m2() // [0, 0]

// x 和 y 都有值的情況
m1({x: 3, y: 8}) // [3, 8]
m2({x: 3, y: 8}) // [3, 8]

// x 有值奕枝,y 無值的情況
m1({x: 3}) // [3, 0]
m2({x: 3}) // [3, undefined]

// x 和 y 都無值的情況
m1({}) // [0, 0];
m2({}) // [undefined, undefined]

m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]
  1. 參數(shù)默認值的位置
  • 如果函數(shù)參數(shù)的默認值不是最后一個棺榔,則這個位置的參數(shù)無法省略
//例一
function f(x=1,y){
    return [x,y]
}
f() //[1,undefined]
f(2) //[2,undefined]
f(,1) //報錯
f(undefined,1) //[1,1]

// 例二
function f(x, y = 5, z) {
  return [x, y, z];
}

f() // [undefined, 5, undefined]
f(1) // [1, 5, undefined]
f(1, ,2) // 報錯
f(1, undefined, 2) // [1, 5, 2]
f(1,undefined) //[1,5,undefined]  

有默認值的參數(shù)都不是最后一個參數(shù)。這時隘道,無法只省略該參數(shù)症歇,而不省略它后面的參數(shù),除非顯式輸入undefined薄声。

如果傳入undefined当船,將觸發(fā)該參數(shù)等于默認值,null則沒有這個效果默辨。

function foo(x = 5, y = 6) {
  console.log(x, y);
}

foo(undefined, null)
// 5 null
  1. 函數(shù)的length屬性
  • 函數(shù)參數(shù)設(shè)置了默認值以后德频,函數(shù)的length屬性的含義是該函數(shù)預(yù)期傳入的參數(shù)個數(shù)
1. 參數(shù)默認值是最后面的,則length返回的是沒有指定默認值得參數(shù)個數(shù),使用參數(shù)總數(shù)減去默認值的個數(shù)
(function (a) {}).length // 1
(function (a = 5) {}).length // 0
(function (a, b, c = 5) {}).length // 2
(function (a,b=1,c=2) {}).length //1 

length屬性的含義是缩幸,該函數(shù)預(yù)期傳入的參數(shù)個數(shù)壹置。某個參數(shù)指定默認值以后竞思,預(yù)期傳入的參數(shù)個數(shù)就不包括這個參數(shù)了。同理钞护,后文的 rest 參數(shù)也不會計入length屬性盖喷。
(function(...args){}).length //0

2. 參數(shù)默認值不是最后面的,則默認值后面的參數(shù)就不再計算
(function (a = 0, b, c) {}).length // 0
(function (a, b = 1, c) {}).length // 1
(function (a,b=1,c,d=4) {}).length // 1 
(function (a,b=1,c=2,d) {}).length // 1 

  1. 作用域
  • 一旦設(shè)置了參數(shù)的默認值难咕,函數(shù)進行聲明初始化時课梳,參數(shù)會形成一個單獨的作用域。等到初始化結(jié)束時余佃,這個作用域就會消失暮刃。而不設(shè)置
    參數(shù)默認值時,就沒有此作用域爆土。
例1:
var x = 1;
function f(x,y=x){
    consoel.log(y);
}
f(2)  //2 
f()  //undefined 

//參數(shù)y的默認值等于變量x,調(diào)用函數(shù)f時椭懊,參數(shù)形成一個單獨的作用域。在這個作用域里步势,y的默認值x指向第一個參數(shù)x,而不是全局變量x,
所以輸出2氧猬。不傳值時,y的值就是undefined

例2:
let x = 1;
function f(y=x){
    let x = 2;
    console.log(y);
}
f() //1 

//未完待續(xù)
  1. rest參數(shù)
  • rest參數(shù)形式為(...參數(shù)名)用于獲取函數(shù)的多余參數(shù)坏瘩,這樣就不要argument對象了盅抚。rest 參數(shù)搭配的變量是一個數(shù)組,
    該變量將多余的參數(shù)放入數(shù)組中桑腮。
1. function add(...values) {
  let sum = 0;

  for (var val of values) {
    sum += val;
  }

  return sum;
}

add(2, 5, 3) // 10

2. 
// arguments變量的寫法
function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort();
}

// rest參數(shù)的寫法
const sortNumbers = (...numbers) => numbers.sort();

arguments對象不是數(shù)組泉哈,而是一個類似數(shù)組的對象。所以為了使用數(shù)組的方法破讨,必須使用Array.prototype.slice.call先將其轉(zhuǎn)為數(shù)組丛晦。rest 參數(shù)就不存在這個問題,它就是一個真正的數(shù)組提陶,數(shù)組特有的方法都可以使用烫沙。

3. 注意,rest 參數(shù)之后不能再有其他參數(shù)(即只能是最后一個參數(shù))隙笆,否則會報錯锌蓄。

// 報錯
function f(a, ...b, c) {
  // ...
}
函數(shù)的length屬性,不包括 rest 參數(shù)撑柔。

(function(a) {}).length  // 1
(function(...a) {}).length  // 0
(function(a, ...b) {}).length  // 1
  1. 箭頭函數(shù)
  • 箭頭函數(shù)等同于匿名函數(shù)
var f = v=>v;

等同于
var f = function(v){
    return v;
}
  • 如果箭頭函數(shù)不需要參數(shù)或這需要多個參數(shù)瘸爽,就使用一個圓括號代表參數(shù)部分
var f = ()=>5;
等同于:
var f = function(){
    return 5;
}

//多個參數(shù)
var sum = (num1,num2)=>num1+num2 
等同于:
var sum = function(num1,num2){
    return num1 + num2 
}

如果箭頭函數(shù)的代碼塊部分多于一條語句,就要使用大括號將它們括起來铅忿,并且使用return語句返回剪决。
var sum = (num1, num2) => { return num1 + num2; }

由于大括號被解釋為代碼塊,所以如果箭頭函數(shù)直接返回一個對象,必須在對象外面加上括號柑潦,否則會報錯享言。
// 報錯
let getTempItem = id => { id: id, name: "Temp" };
// 不報錯
let getTempItem = id => ({ id: id, name: "Temp" });

如果箭頭函數(shù)只有一行語句,且不需要返回值渗鬼,可以采用下面的寫法览露,就不用寫大括號了。
let fn = () => void doesNotReturn();

箭頭函數(shù)可以與變量解構(gòu)結(jié)合使用
const full = ({first,last})=>first + '' + last 
等同于:
function full(person){
    return person.first + '' + person.last;
 }

箭頭函數(shù)使得表達更加簡潔譬胎。
const isEven = n => n % 2 == 0;
const square = n => n * n;
上面代碼只用了兩行差牛,就定義了兩個簡單的工具函數(shù)
  • 箭頭函數(shù)簡化回調(diào)函數(shù)
1.例1 
//正常寫法:
[1,2,3].map(function(x){
    return x*x;
})

//箭頭函數(shù)寫法
[1,2,3].map(x=>x*x)

2. 例2 
// 正常函數(shù)寫法
var result = values.sort(function (a, b) {
  return a - b;
});

// 箭頭函數(shù)寫法
var result = values.sort((a, b) => a - b);

3. rest參數(shù)與箭頭函數(shù)結(jié)合的例子
const numbers = (...nums) => nums 
numbers(1,2,3,4,5) //[1,2,3,4,5]

const headTail = (head,...tail)=>[head,tail]
headTail(1,2,3,4,5)  //[1,[2,3,4,5]]
  • 箭頭函數(shù)注意事項
(1)函數(shù)體內(nèi)的this對象,就是定義時所在的對象银择,而不是使用時所在的對象多糠。

(2)不可以當(dāng)作構(gòu)造函數(shù)累舷,也就是說浩考,不可以使用new命令,否則會拋出一個錯誤被盈。

(3)不可以使用arguments對象析孽,該對象在函數(shù)體內(nèi)不存在。如果要用只怎,可以用 rest 參數(shù)代替袜瞬。

(4)不可以使用yield命令,因此箭頭函數(shù)不能用作 Generator 函數(shù)身堡。
  • 箭頭函數(shù)的this 綁定定義時所在的作用域(父級上下文)邓尤,而不是指向運行時所在的作用域
//ES6 
function foo(){
    setTimeout(()=>
    {
        console.log('id:',this.id)
    },1000)
}
// 上面代碼的this指向轉(zhuǎn)換為ES5為:
function foo(){
    var _this = this;
    setTimeout(function(){
        console.log('id:',_this.id);
    },1000);
}
上面代碼中,轉(zhuǎn)換后的ES5版本清楚地說明了贴谎,箭頭函數(shù)里面根本沒有自己的this汞扎,而是引用外層的this。

數(shù)組擴展

  1. 擴展運算符(...)
  • 擴展運算符好比rest參數(shù)的逆運算擅这,將一個數(shù)組轉(zhuǎn)換為用逗號分隔的參數(shù)序列
console.log(...[1,2,3])  //1 2 3 
console.log(1,...[2,3,4],5) //1 2 3 4 5
[...document.querySelectorAll('div')]  // [<div>, <div>, <div>]

如果擴展運算符后面是一個空數(shù)組澈魄,則不產(chǎn)生任何效果
[...[],1]  //[1] 
  • 主要用于函數(shù)調(diào)用
function push(array, ...items) {
  array.push(...items);
}

function add(x, y) {
  return x + y;
}

var numbers = [4, 38];
add(...numbers) // 42

擴展運算符將一個數(shù)組,變?yōu)閰?shù)序列仲翎。

一個例子是通過push函數(shù)痹扇,將一個數(shù)組添加到另一個數(shù)組的尾部。

// ES5的 寫法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2);

// ES6 的寫法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2);
上面代碼的 ES5 寫法中溯香,push方法的參數(shù)不能是數(shù)組鲫构,所以只好通過apply方法變通使用push方法。
有了擴展運算符玫坛,就可以直接將數(shù)組傳入push方法
  • 擴展運算符的應(yīng)用
    . 合并數(shù)組
        //ES5
        [1,2].concat(more)
        //ES6 
        [1,2,...more]
    
        var arr1 = ['a','b'];
        var arr2 = ['c'];
        var arr3 = ['d','e'];
        //ES5合并:
        arr1.concat(arr2,arr3);  //['a','b','c','d','e']
    
        //ES6合并
        [...arr1,...arr2,...arr3] 
    

對象擴展

  1. 屬性的簡潔表示 ES6允許直接寫入變量和函數(shù)结笨,作為對象的屬性和方法
1. 
var foo = 'bar';
var baz = {foo}
baz //{foo:'bar'}

等同于:
var baz = {foo:foo}

ES6允許在對象之中,直接寫變量。這是禀梳,屬性名為變量名杜窄,屬性值為變量的值。
function f(x, y) {
  return {x, y};
}

// 等同于

function f(x, y) {
  return {x: x, y: y};
}

f(1, 2) // Object {x: 1, y: 2}

2. 除了屬性簡寫算途,方法也可以簡寫
var o = {
    method(){
        return 'hello';
    }
}
等同于:
var o = {
    method:function(){
        return 'hello';
    }
}

再比如:
var birth = '2000/01/01';

var Person = {

  name: '張三',

  //等同于birth: birth
  birth,

  // 等同于hello: function ()...
  hello() { console.log('我的名字是', this.name); }

};

3. 用于函數(shù)返回值
function getPoint(){
    var x =1;
    var y =10;
    return {x,y}
}

getPoint() //{x:1,y:10}
  1. 對象擴展運算符(...)
  • 解構(gòu)賦值
1塞耕、 
使用對象擴展符的解構(gòu)賦值用于從一個對象取值,將所有的可遍歷的嘴瓤,但尚未被讀取的屬性扫外,分配到指定的對象上面。所有的鍵和值都會
被拷貝到新對象上面廓脆。

let {x,y,...z} = {x:1,y:2,a:3,b:4}
x //1 
y //2
z //{a:3,b:4}
變量z是解構(gòu)賦值所在的對象筛谚,它獲取等號右邊的所有尚未讀取的值(a,b),連同值一起拷貝過來。

2. 
由于解構(gòu)賦值要求等號右邊是一個對象停忿,所以如果等號右邊是undefined或null驾讲,就會報錯,因為它們無法轉(zhuǎn)為對象席赂。
let { x, y, ...z } = null; // 運行時錯誤
let { x, y, ...z } = undefined; // 運行時錯誤

3. 
解構(gòu)賦值必須是最后一個參數(shù)吮铭,否則會報錯。

let { ...x, y, z } = obj; // 句法錯誤
let { x, ...y, ...z } = obj; // 句法錯誤

4. 解構(gòu)賦值的拷貝是淺拷貝颅停,即如果一個鍵的值是(數(shù)組,對象,函數(shù)),那么解構(gòu)賦值拷貝的是這個值得引用谓晌,而不是這個值得拷貝
let obj = {a:{b:1}}
let {...x} = obj
obj.a.b = 2;
x.a.b = 2 
上面代碼中,x是解構(gòu)賦值所在的對象癞揉,拷貝了對象obj的a屬性纸肉。a屬性引用了一個對象,修改這個對象的值喊熟,會影響到解構(gòu)賦值對它的引用柏肪。

5. 另外,解構(gòu)賦值不會拷貝繼承自原型對象的屬性逊移。
let o1 = { a: 1 };
let o2 = { b: 2 };
o2.__proto__ = o1;
let { ...o3 } = o2;
o3 // { b: 2 }
o3.a // undefined
上面代碼中预吆,對象o3復(fù)制了o2,但是只復(fù)制了o2自身的屬性胳泉,沒有復(fù)制它的原型對象o1的屬性

再比如:
var o = Object.create({x:1,y:2});
o.z = 3 

let {x,...{y,z}} = o;
x //1 
y //undefined 
z //3 

上面代碼中拐叉,x只是單純的解構(gòu)賦值,所以可以讀取對象o的屬性扇商,變量y和z是雙重解構(gòu)賦值凤瘦,只能讀取對象o自身的屬性,所以只有變量z
賦值成功案铺。

6. 解構(gòu)賦值的一個用處蔬芥,是擴展某個函數(shù)的參數(shù),引入其他操作。

function baseFunction({ a, b }) {
  // ...
}
function wrapperFunction({ x, y, ...restConfig }) {
  // 使用x和y參數(shù)進行操作
  // 其余參數(shù)傳給原始函數(shù)
  return baseFunction(restConfig);
}
上面代碼中笔诵,原始函數(shù)baseFunction接受a和b作為參數(shù)返吻,函數(shù)wrapperFunction在baseFunction的基礎(chǔ)上進行了擴展,能夠接受多余的參數(shù)乎婿,并且保留原始函數(shù)的行為测僵。
  • 擴展運算符
1. 擴展運算符用于取出參數(shù)對象的所有可遍歷屬性,拷貝到當(dāng)前對象之中
let z = {a:3,b:4}
let n = {...z}
n //{a:3,b:4}

2. 合并兩個對象
let ab = {...a,...b}
如果用戶自定義的屬性谢翎,放在擴展運算符后面捍靠,則擴展運算符內(nèi)部的同名屬性會被覆蓋掉。
這用來修改現(xiàn)有對象部分的屬性就很方便了森逮。

let newVersion = {
  ...previousVersion,
  name: 'New Name' // Override the name property
};
上面newVersion自定義了name屬性榨婆,其他屬性全部復(fù)制于previousVersion

3.
 如果擴展運算符后面是一個空對象,則沒有任何效果褒侧。
{...{}, a: 1}
// { a: 1 }


如果擴展運算符的參數(shù)是null或undefined良风,這兩個值會被忽略,不會報錯璃搜。

let emptyObject = { ...null, ...undefined }; // 不報錯

模塊

  • ES6模塊的設(shè)計思想是盡量的靜態(tài)化拖吼,是的編譯時就能確定模塊的依賴關(guān)系,以及輸入和輸出的變量这吻。即ES6可以在編譯時就完成模塊
    加載。

  • 模塊功能主要由兩個命令構(gòu)成:export和import篙议。export命令用于規(guī)定模塊的對外接口唾糯,import命令用于輸入其他模塊提供的功能。

  • export除了輸出變量鬼贱,還可以輸出函數(shù)和類

1. 輸出變量:
export var firstName = 'Michael';
export var lastName = 'Jackson';
export var year = 1958;
等同于:
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;

export {firstName, lastName, year};

2. 輸出函數(shù):
export function multiply(x, y) {
  return x * y;
};

3. 通常情況下移怯,export輸出的變量就是本來的名字,但是可以使用as關(guān)鍵字重命名这难。

function v1() { ... }
function v2() { ... }

export {
  v1 as streamV1,
  v2 as streamV2,
  v2 as streamLatestVersion
};
上面代碼使用as關(guān)鍵字舟误,重命名了函數(shù)v1和v2的對外接口。重命名后姻乓,v2可以用不同的名字輸出兩次嵌溢。

4. export命令規(guī)定的是對外的接口,必須與模塊內(nèi)部的變量建立一對一關(guān)系
// 報錯
export 1;

// 報錯
var m = 1;
export m;
上面兩種寫法都會報錯蹋岩,因為沒有提供對外的接口赖草。第一種寫法直接輸出1,第二種寫法通過變量m剪个,還是直接輸出1秧骑。1只是一個值,不是接口。正確的寫法是下面這樣乎折。

// 寫法一
export var m = 1;

// 寫法二
var m = 1;
export {m};

// 寫法三
var n = 1;
export {n as m};

同樣的绒疗,function和class的輸出,也必須遵守這樣的寫法骂澄。

// 報錯
function f() {}
export f;

// 正確
export function f() {};

// 正確
function f() {}
export {f};

5. export和import不可放在塊級作用域內(nèi) 
  • import
1. 
// main.js
import {firstName, lastName, year} from './profile';

function setName(element) {
  element.textContent = firstName + ' ' + lastName;
}
上面代碼的import命令忌堂,用于加載profile.js文件,并從中輸入變量酗洒。import命令接受一對大括號士修,里面指定要從其他模塊導(dǎo)入的變量名。大括號里面的變量名樱衷,必須與被導(dǎo)入模塊(profile.js)對外接口的名稱相同棋嘲。

如果想為輸入的變量重新取一個名字,import命令要使用as關(guān)鍵字矩桂,將輸入的變量重命名沸移。

import { lastName as surname } from './profile';

2. import 的.js可以省略≈读瘢可以使用相對和絕對路徑雹锣,如果只是模塊名,不帶有路徑癞蚕,需配置路徑蕊爵。

3. import命令具有提升效果,會提升到整個模塊的頭部桦山,首先執(zhí)行攒射。

foo();

import { foo } from 'my_module';
上面的代碼不會報錯,因為import的執(zhí)行早于foo的調(diào)用恒水。這種行為的本質(zhì)是会放,import命令是編譯階段執(zhí)行的,在代碼運行之前钉凌。

4. import * as o  from xxx  可以加載所有輸出值到對象o上


  • export default 為模塊指定默認輸出
1. 使用export default 導(dǎo)出時咧最,import導(dǎo)入可以指定任意名字,且不能使用大括號
// export-default.js
export default function () {
  console.log('foo');
}
上面代碼是一個模塊文件export-default.js御雕,它的默認輸出是一個函數(shù)矢沿。

其他模塊加載該模塊時,import命令可以為該匿名函數(shù)指定任意名字饮笛。

// import-default.js
import customName from './export-default';
customName(); // 'foo'
上面代碼的import命令咨察,可以用任意名稱指向export-default.js輸出的方法,這時就不需要知道原模塊輸出的函數(shù)名福青。
需要注意的是摄狱,這時import命令后面脓诡,不使用大括號

2. export default命令用于指定模塊的默認輸出。顯然媒役,一個模塊只能有一個默認輸出祝谚,因此export default命令只能使用一次。所以酣衷,import命令后面才不用加大括號交惯,因為只可能對應(yīng)一個方法。

3. 
因為export default本質(zhì)是將該命令后面的值穿仪,賦給default變量以后再默認席爽,所以可以直接將一個值寫在export default之后。

// 正確
export default 42;

// 報錯
export 42;
上面代碼中啊片,后一句報錯是因為沒有指定對外的接口只锻,而前一句指定外對接口為default

4. export default也可以用來輸出類。

// MyClass.js
export default class { ... }

// main.js
import MyClass from 'MyClass';
let o = new MyClass();

temp

字符串?dāng)U展

  • JS內(nèi)部字符是以utf-16格式存儲紫谷,每個字符固定2個字節(jié)齐饮。對于那些需要4個字節(jié)存儲的(Unicode 碼點大于0xFFFF的字符),JS會認為它們是兩個字符。
  • 字符串可以使用for...of遍歷
  • ES5只提供了indexof來查找字串笤昨,ES6又提供了3種方法
    1. includes() 返回布爾值祖驱,表示是否找到字串
    2. startsWith() 返回布爾值,表示字串是否在原字符串的開頭
    3. endsWith() 返回布爾值瞒窒,表示字串是否在原字符串的結(jié)尾
1. 
let s = 'Hello world!';

s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true

2.三個方法都支持第二個參數(shù)捺僻,表示搜索開始的位置
let s = 'Hello world!';

s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false

其中endWith的第二個參數(shù)與其他兩個不同,它表示前n個字符根竿,其他兩個表示從第n個位置直到結(jié)束陵像。
  • repeat() 方法返回一個新字符串,表示原字符串重復(fù)n次
1.
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""

2. 如果參數(shù)是小數(shù)寇壳,會被取整
'aa'.repeat(2.9) // aaaaaa

如果參數(shù)是負數(shù)或者Infinity,會報錯
'aa'.repeat(Infinity)   //  RangeError: Invalid count value
'aa'.repeat(-1)  // RangeError: Invalid count value

如果參數(shù)是0~-1 之間的小數(shù),會被先取整為-0妻怎,等價與0
'aa'.repeat(-0.9)  // ""

參數(shù)NaN等同于0 
'aa'.repeat(NaN);   // ""

如果參數(shù)是字符串壳炎,則會先轉(zhuǎn)換為數(shù)字
'aa'.repeat('abc');    // ""
'aa'.repeat('2');   //aaaa
'aa'.repeat(undefined)   // ""
'aa'.repeat(null)   // "" 
  • padStart()用于頭部補全長度,padEnd()用于尾部補全長度
1. padStart()和padEnd()一共接受兩個參數(shù)逼侦,第一個參數(shù)表示指定字符串的最小長度匿辩,第二個參數(shù)是用來補全的字符串。
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'

2. 如果原字符串的長度榛丢,等于或大于 第一個參數(shù)铲球,則返回原字符串
'xxxxx'.padStart(5,'aa')  //  'xxxxx'
'xxxxx'.padEnd(5,'aa')   //  'xxxxx'

3. 如果補全的字符串和原字符串的長度加起來 超過了第一個參數(shù),則會截取超過長度的補全字符串
'abc'.padStart(10, '0123456789')    // '0123456abc'

4. 如果省略了第二個參數(shù)晰赞,則默認使用空格補全長度稼病。
'xxx'.padStart('7')   // "    xxx"

5. 第一個參數(shù)如果是字符串,則會轉(zhuǎn)換為數(shù)字 
'xxx'.padStart('6a','abc') //  "xxx"
'xxx'.padStart('yyyy','abc') //  "xxx"
'xxx'.padStart(null,'abc')   //  "xxx"
'xxx'.padStart(undefined,'abc') //  "xxx"   

6. 常用操作
  1)為數(shù)字補全指定位數(shù)
        '1'.padStart(10, '0') // "0000000001"
        '12'.padStart(10, '0') // "0000000012"
        '123456'.padStart(10, '0') // "0000123456"
  2)設(shè)置字符串格式
        '12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
        '09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"

正則擴展

  • 在ES5中选侨,RegExp構(gòu)造函數(shù)有兩種情況
1. 參數(shù)是字符串,此時第二個參數(shù)是表示正則表達式的修飾符
var regex = new RegExp('xyz','i')
等價于
var regex = /xyz/i;

2. 參數(shù)是一個正則表達式然走,這是會返回一個原正則表達式的拷貝
var regex = new RegExp(/xyz/i)
等價于
var regex = /xyz/i;
但是上面這種情況援制,ES5中不允許使用第二個參數(shù)添加修飾符,否則會報錯芍瑞。

ES6改變了這種情況晨仑,如果RegExp構(gòu)造函數(shù)第一個參數(shù)是一個正則對象,那么可以使用第二個參數(shù)指定修飾符拆檬。并且添加的參數(shù)修飾符洪己,會覆蓋原有的修飾符,只使用指定的修飾符竟贯。
new RegExp(/abc/ig, 'i').flags
// "i"

Es5的source屬性答捕,會返回正則表達式的正文。
/abc/ig.source     // 'abc'

Es6增加了flags屬性澄耍,返回正則表達式的修飾符
/abc/ig.flags      // 'ig'
  • 字符串的正則方法
字符串共有四個方法噪珊,可以使用正則表達式
match()   replace()   search()   split()  
Es6將這四個方法,在內(nèi)部全部調(diào)用RegExp()的實例方法齐莲,從而將所有與正則有關(guān)的方法都定義在RegExp上痢站。

1. String.prototype.match 調(diào)用 RegExp.prototype[Symbol.match]
2. String.prototype.replace 調(diào)用 RegExp.prototype[Symbol.replace]
3. String.prototype.search 調(diào)用 RegExp.prototype[Symbol.search]
4. String.prototype.split 調(diào)用 RegExp.prototype[Symbol.split]  
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市选酗,隨后出現(xiàn)的幾起案子阵难,更是在濱河造成了極大的恐慌,老刑警劉巖芒填,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件呜叫,死亡現(xiàn)場離奇詭異,居然都是意外死亡殿衰,警方通過查閱死者的電腦和手機朱庆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來闷祥,“玉大人娱颊,你說我怎么就攤上這事】常” “怎么了箱硕?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長悟衩。 經(jīng)常有香客問我剧罩,道長,這世上最難降的妖魔是什么座泳? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任惠昔,我火速辦了婚禮幕与,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘舰罚。我一直安慰自己纽门,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布营罢。 她就那樣靜靜地躺著赏陵,像睡著了一般。 火紅的嫁衣襯著肌膚如雪饲漾。 梳的紋絲不亂的頭發(fā)上蝙搔,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死霹菊,一個胖子當(dāng)著我的面吹牛敷存,可吹牛的內(nèi)容都是我干的募舟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了赐写?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤膜赃,失蹤者是張志新(化名)和其女友劉穎挺邀,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跳座,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡端铛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了疲眷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片禾蚕。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖狂丝,靈堂內(nèi)的尸體忽然破棺而出夕膀,到底是詐尸還是另有隱情,我是刑警寧澤美侦,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站魂奥,受9級特大地震影響菠剩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜耻煤,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一具壮、第九天 我趴在偏房一處隱蔽的房頂上張望准颓。 院中可真熱鬧,春花似錦棺妓、人聲如沸攘已。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽样勃。三九已至,卻和暖如春性芬,著一層夾襖步出監(jiān)牢的瞬間峡眶,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工植锉, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辫樱,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓俊庇,卻偏偏與公主長得像狮暑,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子辉饱,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容

  • [TOC] 參考阮一峰的ECMAScript 6 入門參考深入淺出ES6 let和const let和const都...
    郭子web閱讀 1,781評論 0 1
  • 一搬男、ES6簡介 ? 歷時將近6年的時間來制定的新 ECMAScript 標(biāo)準(zhǔn) ECMAScript 6(亦稱 ...
    一歲一枯榮_閱讀 6,071評論 8 25
  • 函數(shù)參數(shù)的默認值 基本用法 在ES6之前,不能直接為函數(shù)的參數(shù)指定默認值鞋囊,只能采用變通的方法止后。 上面代碼檢查函數(shù)l...
    呼呼哥閱讀 3,382評論 0 1
  • 三,字符串?dāng)U展 3.1 Unicode表示法 ES6 做出了改進溜腐,只要將碼點放入大括號译株,就能正確解讀該字符挺益。有了這...
    eastbaby閱讀 1,532評論 0 8
  • 柒黍閱讀 118評論 0 0