let和const
**ES5有兩種定義變量的方法:var和function糊识。ES6一共有6中聲明變量的方法:var,function,let,const以及import和class **
let
- 基本語法
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; // 不報錯
}
}
- 不存在變量提升
var定義變量會產(chǎn)生變量提升的現(xiàn)象抬虽,即變量可以在聲明之前使用,值為undefined纵菌。而let定義的變量阐污,一定要在聲明之后使用,否則就會報錯咱圆。
console.log(foo); //輸出undefined
var foo = 2;
console.log(bar); //let變量聲明之前使用,會報錯ReferenceError
let bar = 2;
- 暫時性死區(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)不跟,才可以獲取和使用該變量颓帝。
- 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 聲明一個只讀的常量窝革,一旦聲明购城,值就不能改變
- const變量聲明時就必須立即初始化,且不能重新賦值
- const變量和let變量一樣,無變量提升,有塊級作用域虐译,不能重復(fù)聲明
- 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ù)組和對象中提取值惊橱,對變量進行賦值
- 數(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'
- 默認值 解構(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還沒有聲明
- 對象的解構(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。方括號這種寫法也祠,屬于“屬性名表達式”昙楚,參見對象的擴展。
- 字符串的解構(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
- 數(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
- 函數(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. 交換變量值
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展
- 模板字符串
- 模板字符串是增強版的字符串坝辫,用反引號(`)標(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ù)擴展
- 函數(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源织。
- 與解構(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]
- 參數(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
- 函數(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
- 作用域
- 一旦設(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ù)
- 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
- 箭頭函數(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ù)組擴展
- 擴展運算符(...)
- 擴展運算符好比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]
對象擴展
- 屬性的簡潔表示 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}
- 對象擴展運算符(...)
- 解構(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種方法
- includes() 返回布爾值祖驱,表示是否找到字串
- startsWith() 返回布爾值,表示字串是否在原字符串的開頭
- 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]