撩課-Web架構(gòu)師養(yǎng)成系列第一篇

前言

Web架構(gòu)師養(yǎng)成系列共15篇,每周更新一篇,主要分享、探討目前大前端領(lǐng)域(前端、后端、移動(dòng)端)企業(yè)中正在用的各種成熟的、新的技術(shù)。
部分文章也會(huì)分析一些框架的底層實(shí)現(xiàn),讓我們做到知其然知其所以然。
本篇文章閱讀需要時(shí)長:約15分鐘

一、ECMAScript 6/7/8簡介

ECMAScript 6.0,簡稱ES6,第一個(gè)版本是在2015年6月進(jìn)行發(fā)布,所以也稱之為《ECMAScript 2015 標(biāo)準(zhǔn)》(簡稱 ES2015)。

JavaScript是ECMAScript的一種實(shí)現(xiàn)(分支),遵循ECMAScript標(biāo)準(zhǔn)的。目前主流瀏覽器已經(jīng)可以完美兼容和使用ES6。ES7/8部分新特性也已經(jīng)被用于我們的實(shí)際開發(fā)中。

image

本篇主要講解ES6的知識(shí)點(diǎn),內(nèi)容如下:let和const、解構(gòu)賦值、字符串操作、函數(shù)、數(shù)組API、集合、對象拷貝、延展操作符、對象補(bǔ)充、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);

運(yùn)行結(jié)果:

Identifier 'site' has already been declared

2)不存在變量提升

 console.log(site);
 let site = 'itLike';
 運(yùn)行結(jié)果:

site is not defined

3)可以定義常量

不能給常量重新賦值,但如果是引用類型的話可以進(jìn)行修改。

// 自然對數(shù)的底

const E = 2.718;

E = 2.71; 

console.log(E);

運(yùn)行結(jié)果: 

Assignment to constant variable.

//  引用類型

const LK = {

   name:'itLike', 

   intro: '喜歡IT, 就上撩課(itLike.com)'

};

LK.name = '撩課';

console.log(LK);

運(yùn)行結(jié)果:
image

4) 塊級作用域

如果用var定義變量,變量是通過函數(shù)或者閉包擁有作用域;但,現(xiàn)在用let定義變量,不僅僅可以通過函數(shù)/閉包隔離,還可以通過塊級作用域隔離。
塊級作用域用一組大括號(hào)定義一個(gè)塊,使用 let 定義的變量在大括號(hào)的外部是訪問不到的,此外,let聲明的變量不會(huì)污染全局作用域。

{let site = 'itLike';}

console.log(site);

運(yùn)行結(jié)果:

site is not defined

if(1){  let str = '小撩'; }

console.log(str);

運(yùn)行結(jié)果: 

str is not defined

5)案例運(yùn)用

高級排他實(shí)現(xiàn)(不再使用閉包)

image

三、解構(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è)置默認(rèn)值

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請求時(shí), 就可以運(yùn)用到解構(gòu)的知識(shí)點(diǎn),代碼如下:

image

四、延展操作符

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}

注意: 如果對象中的屬性一致, 會(huì)被覆蓋

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()用于頭部補(bǔ)全,

padEnd()用于尾部補(bǔ)全; 

第一個(gè)參數(shù)用來指定字符串的最小長度,

第二個(gè)參數(shù)是用來補(bǔ)全的字符串。

//  "2030111111"

let y1 = '2030'.padEnd(10, '1'); 

//   "2030-11-22"

let y2 = '11-22'.padStart(10, '2030-MM-DD');  

console.log(y1, y2);

模板字符串

1) 模板字符串

模板字符串用反引號(hào)(`)包含,變量用${}括起來; 在開發(fā)中使用是非常靈活的。

 let name = '小煤球';
 let sex = '公';
 let result = `我叫 ${name} , 我是 ${sex} 的`;
console.log(result); 
// 我叫 小煤球 , 我是 公 的

2) 模板字符串遍歷插入

image

3) 模板字符串實(shí)現(xiàn)原理

let name = '小煤球';
let sex = '公';
let result = `我叫 ${name} , 我是 ${sex} 的`;
result = result.replace(/\${([^}]*)}/g);
console.log(result);

六、函數(shù)操作

1) 設(shè)置默認(rèn)參數(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ù);
而右邊則是進(jìn)行的操作以及返回的值 inputs => output。

 ["趙薇", "王菲", "那英"].forEach(
 val => console.log(val)
 );

注意:

1)多個(gè)參數(shù)要用()包起來,函數(shù)體有多條語句需要用{}包起來;
2)箭頭函數(shù)根本沒有自己的this,所以內(nèi)部的this就是外層代碼塊的this。 正是因?yàn)樗鼪]有this,從而避免了this指向的問題;
3)箭頭函數(shù)中沒有arguments對象。

image

注意:

1)let聲明的變量不會(huì)放在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()

將一個(gè)數(shù)組或者類數(shù)組變成新數(shù)組,是淺拷貝操作。

let oldArr = [

    '小煤球', 10, 
 
     {df1: '小Python',  df2: '土豆'}

 ];
 
 let newArr = Array.from(oldArr);

 console.log(newArr === oldArr); // false

2)Array.of()

創(chuàng)建一個(gè)具有可變數(shù)量參數(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()

用一個(gè)固定值填充一個(gè)數(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('撩'));

運(yùn)行結(jié)果:

image

八、對象操作

8.1 屬性簡寫

如果對象中屬性值和變量名一樣,并且屬性的值就是變量表示值,則簡寫。

image

8.2 super

通過super可以調(diào)用prototype上的屬性或方法。

image

8.3 Object.is

對比兩個(gè)值是否相等

> console.log(Object.is(Array, Object));

**8.4  Object.setPrototypeOf**

將一個(gè)指定的對象的原型設(shè)置為另一個(gè)對象或者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)用實(shí)現(xiàn)

image

九、類操作

在之前定義類是通過構(gòu)造函數(shù)來操作的,es6新增了class關(guān)鍵字,此時(shí),我們也可以像其它語言一樣來創(chuàng)建各種類了。

class Person{

constructor(name, age){

    this.name = name;

    this.age = age;

}

print(){

    console.log('我叫' + this.name + ',今年' + this.age + '歲');

}

}

類的繼承

小案例:五彩小球

運(yùn)行效果:

image

核心代碼:

image
image

十、集合操作

1set

一個(gè)Set是一堆東西的集合,Set有點(diǎn)像數(shù)組,不過跟數(shù)組不一樣的是,Set里面不能有重復(fù)的內(nèi)容;

> // 創(chuàng)建一個(gè)集合
  
  let set = new Set(['張三', '李四', '王五', '張三', '李四']);
  
  console.log(set);
  
  // 一個(gè)屬性
  
  console.log(set.size);
  
  // 四個(gè)方法
  
  // 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)實(shí)現(xiàn)。
如果你需要“鍵值對”的數(shù)據(jù)結(jié)構(gòu),Map比Object更合適。
它類似于對象,也是鍵值對的集合,但是“鍵”的范圍不限于字符串,各種類型的值(包括對象)都可以當(dāng)作鍵。
實(shí)例屬性和方法:size、set、get、has、delete、clear

  // 創(chuàng)建一個(gè)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);
  
  });
  
  // 注意事項(xiàng)
  
  map.set({}, '呵呵呵呵呵');
  
  map.set({}, '哈哈哈哈');
  
  console.log(map);
  
  console.log({} === {});

十一、Generator

為什么要使用generator?

開發(fā)中, 比如在做網(wǎng)絡(luò)請求時(shí)我們會(huì)進(jìn)行異步調(diào)用,為了保證調(diào)用順序的正確性,通常我們會(huì)用回調(diào)函數(shù),也可以采用Promise相關(guān)的技術(shù)來操作。
還有一種常用的解決方案,它就是Generator生成器函數(shù)。
顧名思義,它是一個(gè)生成器,它也是一個(gè)狀態(tài)機(jī),內(nèi)部擁有值及相關(guān)的狀態(tài),生成器返回一個(gè)迭代器Iterator對象,我們可以通過這個(gè)迭代器,手動(dòng)地遍歷相關(guān)的值、狀態(tài),保證正確的執(zhí)行順序。

1)聲明

Generator的聲明方式類似一般的函數(shù)聲明,只是多了個(gè)*號(hào),并且一般可以在函數(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());

迭代器有一個(gè)next方法,每次執(zhí)行的時(shí)候會(huì)返回一個(gè)對象,對象里面有兩個(gè)屬性,一個(gè)是value表示返回的值,還有就是布爾值done,表示是否迭代完成。

2)模擬實(shí)現(xiàn)

image

十二、Proxy&&Reflect (了解)

從語法角度講JavaScript不支持重載。
原因很簡單,JS中函數(shù)可以傳入任意類型、任意個(gè)數(shù)的參數(shù),
通通可以通過在函數(shù)內(nèi)使用this.arguments獲得。
這樣,就無法實(shí)現(xiàn)同名函數(shù)參數(shù)列表不同實(shí)現(xiàn)不同功能。
當(dāng)然,在實(shí)際使用過程中,可以人為去檢測傳入實(shí)參的個(gè)數(shù)及類型,來進(jìn)行不同操作。
但是,這不能叫做重載。
ES6帶來了Proxy和Reflect,配合使用可以實(shí)現(xiàn)重載。
Proxy用于修改某些操作的默認(rèn)行為,相當(dāng)于對原始想進(jìn)行的操作進(jìn)行“包裝”;
Reflect對象的方法與Proxy對象的方法一一對應(yīng),這使得Proxy對象可以方便的調(diào)用對應(yīng)的Reflect方法完成默認(rèn)行為。

set實(shí)現(xiàn):

image

PS: 什么時(shí)重載?

簡單說,就是函數(shù)或者方法有相同的名稱,但是參數(shù)列表不相同的情形,這樣的同名不同參數(shù)的函數(shù)或者方法之間,互相稱之為重載函數(shù)或者方法。

獲取代碼,有疑惑、答疑,加我微信yejh9522溝通交流即可;下篇更新預(yù)告: ES7/8新特性,Async和Promise

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 第2章 基本語法 2.1 概述 基本句法和變量 語句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,557評論 0 13
  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔,今天18年5月份再次想寫文章,發(fā)現(xiàn)簡書還為我保存起的...
    Jenaral閱讀 3,143評論 2 9
  • 現(xiàn)在有兩種人,一種滿懷憧憬遠(yuǎn)出求學(xué),一種盡是煩惱等待就業(yè)。而我屬于后者。全國每年有數(shù)不盡的失業(yè)者,待業(yè)者,而大學(xué)畢...
    小香彬閱讀 164評論 0 1
  • 晨時(shí),火光在眼瞼上燃起 永恒的時(shí)間必曾宣揚(yáng) 灼熱感與火焰的剝離 明亮一些 再明亮一些 就會(huì)有人取出一捆柴火 焚盡心...
    尋槳閱讀 342評論 3 9
  • 經(jīng)常有人問:創(chuàng)業(yè)最大的挑戰(zhàn)是什么? 對此,每個(gè)人都有不同的答案。我個(gè)人覺得,創(chuàng)業(yè)最大的挑戰(zhàn)是如何面對變化,并且在變...
    王梓懿閱讀 294評論 0 1

友情鏈接更多精彩內(nèi)容