前言
Web架構(gòu)師養(yǎng)成系列共15篇牺六,每周更新一篇颤枪,主要分享、探討目前大前端領(lǐng)域(前端淑际、后端畏纲、移動端)企業(yè)中正在用的各種成熟的、新的技術(shù)春缕。
部分文章也會分析一些框架的底層實現(xiàn)盗胀,讓我們做到知其然知其所以然。
本篇文章閱讀需要時長:約15分鐘
一淡溯、ECMAScript 6/7/8簡介
ECMAScript 6.0读整,簡稱ES6簿训,第一個版本是在2015年6月進行發(fā)布咱娶,所以也稱之為《ECMAScript 2015 標準》(簡稱 ES2015)。
JavaScript是ECMAScript的一種實現(xiàn)(分支)强品,遵循ECMAScript標準的膘侮。目前主流瀏覽器已經(jīng)可以完美兼容和使用ES6。ES7/8部分新特性也已經(jīng)被用于我們的實際開發(fā)中的榛。
本篇主要講解ES6的知識點琼了,內(nèi)容如下:let和const、解構(gòu)賦值、字符串操作雕薪、函數(shù)昧诱、數(shù)組API、集合所袁、對象拷貝盏档、延展操作符跟畅、對象補充砂吞、Generator戳表、Proxy挠进、Reflect硝训。
二带污、let和const
ES6新增了let和const來聲明變量楞卡,主要是解決var聲明變量所造成的困擾和問題:
var不能用于定義常量
var可以重復(fù)聲明變量
var存在變量提升
var不支持塊級作用域
而let和const解決了以上問題柏副,具體操作如下:
1)不可以重復(fù)聲明變量
let site = 'itLike';
let site = 'itLike';
console.log(site);
運行結(jié)果:
Identifier 'site' has already been declared
2)不存在變量提升
console.log(site);
let site = 'itLike';
運行結(jié)果:
site is not defined
3)可以定義常量
不能給常量重新賦值港华,但如果是引用類型的話可以進行修改道川。
// 自然對數(shù)的底
const E = 2.718;
E = 2.71;
console.log(E);
運行結(jié)果:
Assignment to constant variable.
// 引用類型
const LK = {
name:'itLike',
intro: '喜歡IT, 就上撩課(itLike.com)'
};
LK.name = '撩課';
console.log(LK);
運行結(jié)果:
4) 塊級作用域
如果用var定義變量,變量是通過函數(shù)或者閉包擁有作用域苹丸;但愤惰,現(xiàn)在用let定義變量,不僅僅可以通過函數(shù)/閉包隔離赘理,還可以通過塊級作用域隔離宦言。
塊級作用域用一組大括號定義一個塊,使用 let 定義的變量在大括號的外部是訪問不到的商模,此外奠旺,let聲明的變量不會污染全局作用域。
{let site = 'itLike';}
console.log(site);
運行結(jié)果:
site is not defined
if(1){ let str = '小撩'; }
console.log(str);
運行結(jié)果:
str is not defined
5)案例運用
高級排他實現(xiàn)(不再使用閉包)
三施流、解構(gòu)賦值
用于分解js中對象的結(jié)構(gòu)响疚。
1) 用于數(shù)組的結(jié)構(gòu)
// 普通寫法
let nameArr = ['撩課', '小撩', '小煤球'];
let name1 = nameArr[0];
let name2 = nameArr[1];
let name3 = nameArr[2];
// 解構(gòu)寫法
let [name1, name2, name3] = nameArr;
console.log(name1, name2, name3);
2)對象的解構(gòu)
// 寫法1
let {name, age, sex}
= {name: '小煤球', age: 1, sex: '公'};
// 結(jié)果: 小煤球 1 公
console.log(name, age, sex);
// 寫法2: 解構(gòu)重命名
let {name: lkName, age: lkAge, sex: lkSex}
= {name: '小煤球', age: 1, sex: '公'};
// 結(jié)果: 小煤球 1 公
console.log(lkName, lkAge, lkSex);
// 寫法3: 可以設(shè)置默認值
let {name, age, sex = '公'}
= {name: '小煤球', age: 1};
console.log(sex); // 公
// 寫法4:省略解構(gòu)
let [, , sex] = ['小煤球', 1, '公 '];
console.log(sex);
3) 應(yīng)用場景
在封裝ajax的GET和POST請求時, 就可以運用到解構(gòu)的知識點,代碼如下:
四瞪醋、延展操作符
1)延展數(shù)組
let arr1 = [ 'a', 'b', 'c'];
let arr2 = [1, 2, 3];
let result = [...arr1, ...arr2];
console.log(result);
// [ "a", "b", "c", 1, 2, 3 ]
2)延展對象
let smallDog = {name:'小煤球', age: 1};
let bigDog = {name: 'Python', age: 2};
let dog = {...smallDog, ...bigDog};
console.log(dog);
// {name: "Python", age: 2}
注意: 如果對象中的屬性一致, 會被覆蓋
3)開發(fā)應(yīng)用場景
function getMinValue() {
console.log(Math.min(...arguments));
}
getMinValue(1, -99, 22, 10, 9); // -99
五忿晕、字符串操作
新增字符串方法
1) startsWith()
判斷字符串是否以 XX 開頭
let url = 'http://www.itlike.com';
console.log(url.startsWith('http')); // true
2) endsWith()
判斷字符串是否以 XX 結(jié)尾
let file = 'index.html';
console.log(file.endsWith('html')); // true
3) includes()
判斷字符串中是否包含 XX
let str = 'liaoke';
console.log(str.includes('ao')); // true
4) repeat()
拷貝n份
let title = '撩課在線';
console.log(title.repeat(100));
5) padStart() / padEnd()
padStart()用于頭部補全,
padEnd()用于尾部補全;
第一個參數(shù)用來指定字符串的最小長度银受,
第二個參數(shù)是用來補全的字符串践盼。
// "2030111111"
let y1 = '2030'.padEnd(10, '1');
// "2030-11-22"
let y2 = '11-22'.padStart(10, '2030-MM-DD');
console.log(y1, y2);
模板字符串
1) 模板字符串
模板字符串用反引號(`)包含,變量用${}括起來; 在開發(fā)中使用是非常靈活的宾巍。
let name = '小煤球';
let sex = '公';
let result = `我叫 ${name} , 我是 ${sex} 的`;
console.log(result);
// 我叫 小煤球 , 我是 公 的
2) 模板字符串遍歷插入
3) 模板字符串實現(xiàn)原理
let name = '小煤球';
let sex = '公';
let result = `我叫 ${name} , 我是 ${sex} 的`;
result = result.replace(/\${([^}]*)}/g);
console.log(result);
六咕幻、函數(shù)操作
1) 設(shè)置默認參數(shù)
function logPerson(name, sex = '男', age = 20) {
console.log(name);
console.log(sex);
console.log(age);
}
// undefined 男 20
logPerson();
2)延展參數(shù)轉(zhuǎn)化
let logName = function (arg1, ...arg2) {
console.log(arg1, arg2);
};
// 宋小寶 , ["趙薇", "王菲", "那英"]
logName('宋小寶', '趙薇', '王菲', '那英');
3)箭頭函數(shù)
箭頭函數(shù)簡化了函數(shù)的的定義方式;
一般以 "=>" 操作符左邊為輸入的參數(shù);
而右邊則是進行的操作以及返回的值 inputs => output。
["趙薇", "王菲", "那英"].forEach(
val => console.log(val)
);
注意:
1)多個參數(shù)要用()包起來顶霞,函數(shù)體有多條語句需要用{}包起來肄程;
2)箭頭函數(shù)根本沒有自己的this,所以內(nèi)部的this就是外層代碼塊的this。 正是因為它沒有this蓝厌,從而避免了this指向的問題玄叠;
3)箭頭函數(shù)中沒有arguments對象。
注意:
1)let聲明的變量不會放在window上
2)對象不是作用域
let site = 'like.com';
let obj = {
site: '撩課',
func: () => {
// this指向window
console.log(this);
// undefined
console.log(this.site);
}
};
let func = obj.func;
func();
七拓提、數(shù)組新增方法
ES6中在原有數(shù)組的方法上又新增了一些好用的方法诸典,比如:forEach、findIndex崎苗、find狐粱、map、reduce胆数、filter肌蜻、every、some等必尼。
1)Array.from()
將一個數(shù)組或者類數(shù)組變成新數(shù)組蒋搜,是淺拷貝操作。
let oldArr = [
'小煤球', 10,
{df1: '小Python', df2: '土豆'}
];
let newArr = Array.from(oldArr);
console.log(newArr === oldArr); // false
2)Array.of()
創(chuàng)建一個具有可變數(shù)量參數(shù)的新數(shù)組實例判莉,而不考慮參數(shù)的數(shù)量或類型豆挽。
// [8]
console.log(Array.of(8));
// [1, 2, 3]
console.log(Array.of(1, 2, 3));
// [ , , , , , , ]
console.log(Array(8));
// [1, 2, 3]
console.log(Array(1, 2, 3));
3)Array.fill()
用一個固定值填充一個數(shù)組中從起始索引到終止索引內(nèi)的全部元素。
語法結(jié)構(gòu):arr.fill(value[, start[, end]])
let array1 = [1, 2, 3, 4, 5];
// 用 撩 替換 索引[2,5]中的內(nèi)容
console.log(array1.fill('撩', 2, 5));
// 用 撩 替換 索引[1]中的內(nèi)容
console.log(array1.fill('撩', 1));
// 用 撩 替換 數(shù)組中所有內(nèi)容
console.log(array1.fill('撩'));
運行結(jié)果:
八券盅、對象操作
8.1 屬性簡寫
如果對象中屬性值和變量名一樣帮哈,并且屬性的值就是變量表示值,則簡寫锰镀。
8.2 super
通過super可以調(diào)用prototype上的屬性或方法娘侍。
8.3 Object.is
對比兩個值是否相等
> console.log(Object.is(Array, Object));
**8.4 Object.setPrototypeOf**
將一個指定的對象的原型設(shè)置為另一個對象或者null
let dog1 = { name: '小煤球' };
let obj = {name: 'xxx'};
Object.setPrototypeOf(dog1, obj);
let dog2 = {
__proto__: obj
};
console.log(dog1.__proto__.name);
console.log(dog2.__proto__.name);
**8.5 對象拷貝-深拷貝和淺拷貝**
**1)淺拷貝**
Object.assign拷貝
let obj1 = { dog1: { name: '小煤球' } };
let obj2 = { name: '小Python' };
let obj = {};
Object.assign(obj, obj1, obj2);
console.log(obj);
延展拷貝
let obj1 = { dog1: { name: '小煤球' } };
let obj2 = { name: '小Python' };
console.log({ ...obj1, ...obj2 });
2)深拷貝
JSON.parse和JSON.stringify
let obj1 = { dog1: { name: '小煤球' } };
let obj2 = { name: '小Python' };
console.log(JSON.parse(JSON.stringify({ ...obj1, ...obj2 })));
遞歸調(diào)用實現(xiàn)
九、類操作
在之前定義類是通過構(gòu)造函數(shù)來操作的泳炉,es6新增了class關(guān)鍵字憾筏,此時,我們也可以像其它語言一樣來創(chuàng)建各種類了花鹅。
class Person{
constructor(name, age){ this.name = name; this.age = age; } print(){ console.log('我叫' + this.name + ',今年' + this.age + '歲'); }
}
類的繼承
小案例:五彩小球
運行效果:
核心代碼:
十氧腰、集合操作
1set
一個Set是一堆東西的集合,Set有點像數(shù)組刨肃,不過跟數(shù)組不一樣的是古拴,Set里面不能有重復(fù)的內(nèi)容;
> // 創(chuàng)建一個集合
let set = new Set(['張三', '李四', '王五', '張三', '李四']);
console.log(set);
// 一個屬性
console.log(set.size);
// 四個方法
// add
console.log(set.add('劉德華').add('旋之華'));
console.log(set);
// delete
console.log(set.delete('張三'));
console.log(set.delete('李四'));
console.log(set);
// has
console.log(set.has('張三'));
console.log(set.has('張三1'));
// clear
console.log(set.clear()); // undefined
console.log(set);
2)map
Map結(jié)構(gòu)提供了“值—值”的對應(yīng)之景,是一種更完善的Hash結(jié)構(gòu)實現(xiàn)斤富。
如果你需要“鍵值對”的數(shù)據(jù)結(jié)構(gòu)膏潮,Map比Object更合適锻狗。
它類似于對象,也是鍵值對的集合,但是“鍵”的范圍不限于字符串轻纪,各種類型的值(包括對象)都可以當作鍵油额。
實例屬性和方法:size、set刻帚、get潦嘶、has、delete崇众、clear
// 創(chuàng)建一個Map
let obj1 = {a: 1}, obj2 = {b: 2};
const map = new Map([
['name', '張三'],
['age', 18],
['sex', '男'],
[obj1, '今天天氣很好'],
[obj2, '適合敲代碼'],
[[1,2], 'hhh']
]);
console.log(map);
console.log(map.size);
// set和get
map.set('friends', ['趙六', '力氣']).set(['dog'], '小花');
console.log(map);
console.log(map.get('name'));
console.log(map.get(obj1));
// delete
map.delete(obj1);
console.log(map.delete('xxxx'));
console.log(map);
// has
console.log(map.has(obj1));
console.log(map.has(obj2));
// clear
map.clear();
console.log(map);
// 遍歷
map.forEach(function (value, index) {
console.log(index + ':' + value);
});
// 注意事項
map.set({}, '呵呵呵呵呵');
map.set({}, '哈哈哈哈');
console.log(map);
console.log({} === {});
十一掂僵、Generator
為什么要使用generator?
開發(fā)中, 比如在做網(wǎng)絡(luò)請求時我們會進行異步調(diào)用顷歌,為了保證調(diào)用順序的正確性锰蓬,通常我們會用回調(diào)函數(shù),也可以采用Promise相關(guān)的技術(shù)來操作眯漩。
還有一種常用的解決方案芹扭,它就是Generator生成器函數(shù)。
顧名思義赦抖,它是一個生成器舱卡,它也是一個狀態(tài)機,內(nèi)部擁有值及相關(guān)的狀態(tài)队萤,生成器返回一個迭代器Iterator對象轮锥,我們可以通過這個迭代器,手動地遍歷相關(guān)的值要尔、狀態(tài)交胚,保證正確的執(zhí)行順序。
1)聲明
Generator的聲明方式類似一般的函數(shù)聲明盈电,只是多了個*號蝴簇,并且一般可以在函數(shù)內(nèi)看到y(tǒng)ield關(guān)鍵字。
function* showNames() {
yield '張三';
yield '李四';
return '王五';
}
let show = showNames();
// {done: false, value: "張三"}
console.log(show.next());
// {done: false, value: "李四"}
console.log(show.next());
// {done: true, value: "王五"}
console.log(show.next());
// {done: true, value: undefined}
console.log(show.next());
迭代器有一個next方法匆帚,每次執(zhí)行的時候會返回一個對象熬词,對象里面有兩個屬性,一個是value表示返回的值吸重,還有就是布爾值done互拾,表示是否迭代完成。
2)模擬實現(xiàn)
十二嚎幸、Proxy&&Reflect (了解)
從語法角度講JavaScript不支持重載颜矿。
原因很簡單,JS中函數(shù)可以傳入任意類型嫉晶、任意個數(shù)的參數(shù)骑疆,
通通可以通過在函數(shù)內(nèi)使用this.arguments獲得田篇。
這樣,就無法實現(xiàn)同名函數(shù)參數(shù)列表不同實現(xiàn)不同功能箍铭。
當然泊柬,在實際使用過程中,可以人為去檢測傳入實參的個數(shù)及類型诈火,來進行不同操作兽赁。
但是,這不能叫做重載冷守。
ES6帶來了Proxy和Reflect刀崖,配合使用可以實現(xiàn)重載。
Proxy用于修改某些操作的默認行為拍摇,相當于對原始想進行的操作進行“包裝”蒲跨;
Reflect對象的方法與Proxy對象的方法一一對應(yīng),這使得Proxy對象可以方便的調(diào)用對應(yīng)的Reflect方法完成默認行為授翻。
set實現(xiàn):
PS: 什么時重載或悲?
簡單說,就是函數(shù)或者方法有相同的名稱堪唐,但是參數(shù)列表不相同的情形巡语,這樣的同名不同參數(shù)的函數(shù)或者方法之間,互相稱之為重載函數(shù)或者方法淮菠。
獲取代碼男公,有疑惑、答疑合陵,加我微信yejh9522溝通交流即可枢赔;下篇更新預(yù)告: ES7/8新特性,Async和Promise