JS的ES6知識點詳解

1.let-const塊級作用域的補充

const names=["abc","cba","nba"];

for(let  i=0;i<names.length;i++){ //* 這個數(shù)組的元素有三個篙程,所以會形成3個塊級作用域
  console.log(names[i]);
}

以上for遍歷內(nèi)部的實現(xiàn)是以下這樣的:

因為數(shù)組有3個元素,所以會產(chǎn)生3個塊級作用域别厘。

//第一個塊級作用域
{
    let i=0;
    console.log(names[i])
}
//第二個塊級作用域
{
    把上次i++的結(jié)果賦值新定義的i //注意i++的i和let i不是同一個虱饿,js引擎會在內(nèi)部做一些處理,這里為了方便讓我們理解內(nèi)部的實現(xiàn)
    let i=結(jié)果
    console.log(names[i]);
}
//第三個塊級作用域
{
    把上次i++的結(jié)果賦值給新定義的i
    let i=結(jié)果
    console.log(names[i]);
}

所以每個塊級作用域的i都不是同一個。

那使用const定義是不是可以實現(xiàn)呢?

如果將上面的代碼換一下:

const names=["abc","cba","nba"];

for(const  i=0;i<names.length;i++){ //* 這個數(shù)組的元素有三個氮发,所以會形成3個塊級作用域
  console.log(names[i]);
}

同樣地渴肉,因為names有三個元素,所以還是會形成三個作用域折柠。內(nèi)部實現(xiàn)是這樣的:

//第一個塊級作用域
{
    const i=0;
    console.log(names[i]);
}
//第二個塊級作用域 此時在i++的時候會報錯宾娜,因為const本質(zhì)是值不能改變,所以就會拋出錯誤
{
    //注意i++的i和const i不是同一個扇售,js引擎會在內(nèi)部做一些處理前塔,這里為了方便讓我們理解內(nèi)部的實現(xiàn)
    將i++的結(jié)果賦值給新定義的i  //這一行就開始報錯
    const i=結(jié)果
}

1.1 for...of 遍歷可迭代的數(shù)組(或?qū)ο?

const names=["abc","cba","nba"];

for(const item of names){ //* 這個數(shù)組的元素有三個,所以會形成3個塊級作用域
  console.log(item);
}

for...of是將數(shù)組或?qū)ο竺總€元素取出來

內(nèi)部實現(xiàn):因為數(shù)組有3個元素承冰,所以還是會形成3個塊級作用域

//第一個塊級作用域
{
    const item="abc";
    console.log(item)
}
//第二個塊級作用域
{
    const item="cba";
    console.log(item)
}
//第三個塊級作用域
{
    const item="nba";
    console.log(item)
}

這里每個塊級作用域的item都不是同一個

2.暫時性死區(qū)

在ES6中华弓,我們還有一個概念稱之為暫時性死區(qū):

  • 它表達(dá)的意思是在一個代碼塊中,使用let困乒、const聲明的變量寂屏,在聲明之前不可以訪問的
  • 我們將這種現(xiàn)象稱之為 temporal dead zone(暫時性死區(qū),TDZ)(社區(qū))

以下兩段代碼都形成了暫時性死區(qū)娜搂,在let迁霎、const聲明之前,不能進行訪問百宇。

var foo="foo";

if(true){
  console.log(foo);
  let foo="abc"; //* Cannot access 'foo' before initialization
}
var foo="foo";
function bar(){
  console.log(foo);
  let foo="abc";
}

bar()

3.var考廉、let、const的選擇

對于var的使用:

  • var有其自身的特殊性:作用域提升携御、在window對象上添加屬性昌粤、沒有塊級作用域,這些都是歷史遺留問題
  • 其實這是javascript設(shè)計之初的一種語言缺陷
  • 目前市場上也在利用這種缺陷出一系列的面試題啄刹,來考察大家對JavaScript語言本身以及底層的理解
  • 但是在實際工作中涮坐,我們可以使用最新的規(guī)范來編寫,也就是不再使用var來定義變量了誓军。

對于let袱讹、const來說

  • 對于let、const昵时,是目前開發(fā)中推薦使用的
  • 我們優(yōu)先推薦使用const捷雕,這樣可以保證數(shù)據(jù)的安全性不會被隨意的篡改
  • 只有當(dāng)我們明確知道一個變量后續(xù)會需要被重新賦值時這個時候再使用let
  • 這種在很多其他語言里面也都是一種約定俗成的規(guī)范债查,盡量我們也遵守這種規(guī)范非区。

4.字符串模板基本使用

在ES6之前,如果我們想要使用字符串和動態(tài)的變量(標(biāo)識符)拼接在一起盹廷,是非常麻煩和丑陋的(ugly)

ES6允許我們使用字符串模板來嵌入JS的變量或表達(dá)式來進行拼接:

  • 首先征绸,我們會使用``符號來編寫字符串,稱之為 模板字符串
  • 其次,在模板字符串中管怠,我們可以通過${expresion}來嵌入動態(tài)的內(nèi)容
// * 在ES6之前拼接字符串和動態(tài)的變量在一起淆衷,是非常麻煩的
var name="wjy";
var age=18;
var height=1.6
console.log("我的名字是:"+name+" 年齡是:"+age+" 身高:"+height);

在ES6中提供了模板字符串 ``

如果需要引用動態(tài)變量:${變量名}

// *在ES6當(dāng)中,提供了一個模板字符串 `` 引用動態(tài)變量是:${變量名}
const name="wjy";
const age=18;
const height=1.66
console.log(`我的名字是${name} 年齡是:${age} 身高:${height}`)

5.標(biāo)簽?zāi)0遄址?/h3>

模板字符串還有另外一種用法:標(biāo)簽?zāi)0遄址?(Tagged Template Literals)

普通JavaScript的函數(shù)調(diào)用

function foo(m,n){
  console.log(m,n);
}
// * 函數(shù)調(diào)用最普通的方式
foo(20,39)

如果我們使用標(biāo)簽?zāi)0遄址吵冢⑶以谡{(diào)用的時候插入其他的變量:

  • 模板字符串被拆分了
  • 第一個元素是數(shù)組祝拯,是被模板字符串拆分的字符串組合
  • 后面的元素是一個個模板字符串傳入的內(nèi)容
function foo(m,n){
  console.log(m,n);
}
// * 函數(shù)調(diào)用最普通的方式
foo(20,39)
// * 另外調(diào)用函數(shù)的方式:標(biāo)簽?zāi)0遄址?
foo``;//[ '' ] undefined
foo`hello World` //[ 'hello World' ] undefined
const name="wjy";
const age=20;
// * 第一個參數(shù)依然是模板字符串的完整字符串,只是被切成了多塊她肯,放到了數(shù)組中   第二個參數(shù)是 模板字符串中佳头,第一個${expression}的expression的值
foo`Hello${age}Wo${name}rld`;//[ 'Hello', 'Wo', 'rld' ] wjy

6.函數(shù)的默認(rèn)參數(shù)

在ES5的時候,可以給參數(shù)設(shè)置值晴氨,使用的是 邏輯或:如果前面為真康嘉,則返回前面的表達(dá)式的值,如果前面為false則將后面的表達(dá)式的值返回籽前。

但是存在缺陷:

  • 寫起來比較麻煩亭珍,閱讀性差
  • 存在缺陷:如果傳入的值是0或者是"",但還是設(shè)置"aaa"或"bbb"
function foo(m,n){
  // * 如果沒有給函數(shù)傳參:那么m,n會是undefined枝哄,如果對m肄梨、n進行操作時,很容易產(chǎn)生錯誤
  // * ES5之前是怎么給參數(shù)默認(rèn)值 邏輯或
  /**
   * 缺點:
   * 1.寫起來很麻煩 挠锥,并且代碼的閱讀性比較差
   * 2.這種寫起來是有bug 如果傳入的是 0 "" ,但是會被設(shè)置 為"aaa"或"bbb"
   * 
   */
 m=m|| "aaa";
 n=n||"bbb"
  console.log(m,n);
}
foo();
foo(100);
foo(100,200)

但在ES6中提供了給函數(shù)的參數(shù)設(shè)置默認(rèn)值众羡,直接參數(shù)后面使用="值"

function foo(m="aaa",n="bbb"){
  console.log(m,n);
}

foo();//aaa bbb
foo(100);//100 bbb
foo(100,200);//100 200

上面的代碼,轉(zhuǎn)化為ES5是這樣的:

"use strict";

function foo() {
  var m =
    arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : "aaa";
  var n =
    arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "bbb";
  console.log(m, n);
}

foo(); //aaa bbb

foo(100); //100 bbb

foo(100, 200); //100 200

6.1 函數(shù)的默認(rèn)值

// * 可以傳基本數(shù)據(jù)類型
function foo(m="aaa",n="bbb"){
  console.log(m,n);
}

foo();//aaa bbb
foo(100);//100 bbb
foo(100,200);//100 200

6.7 函數(shù)默認(rèn)值的補充

  1. 默認(rèn)值也可以和解構(gòu)一起使用

    function printInfo({name,age}={name:"wjy",age:18}){
      console.log(name,age);
    }
    printInfo()
    
    // * 另外一個寫法
    function printInfo({name="wjy",age=20}={}){
      console.log(name,age);
    }
    
    printInfo()
    
  2. 另外參數(shù)的默認(rèn)值我們通常會放到最后(在很多語言中瘪贱,如果不放到最后其實會報錯的)

    • 但是Javascript允許不將其放到最后纱控,但是意味著還是會按照順序來匹配
  3. 另外默認(rèn)值會改變函數(shù)的length的個數(shù)辆毡,默認(rèn)值以及后面的參數(shù)都不計算在length之內(nèi)的

// * 有默認(rèn)值的函數(shù)的length屬性
console.log(bar.length); //2

function baz(x=20,y,z){

}
console.log(baz.length);//0

7.函數(shù)的剩余參數(shù)

ES6中引用了rest parameter菜秦,可以將不定數(shù)量的參數(shù)放入到一個數(shù)組中:

如果最后一個參數(shù)是以...為前綴,那么它會將剩余的參數(shù)放到該參數(shù)中舶掖,并且作為一個數(shù)組

那么arguments和剩余參數(shù)有什么區(qū)別球昨?

  • 剩余參數(shù)只包含沒有對應(yīng)形參的實參,而arguments包含傳遞給函數(shù)的所有實參
  • arguments對象不是一個真正的數(shù)組眨攘,而剩余參數(shù)是一個真正的數(shù)組主慰,可以進行數(shù)組的所有操作。
  • arguments是早期的ECMAScript中為了方便去獲取所有的參數(shù)提供的一個數(shù)據(jù)結(jié)構(gòu)鲫售,而剩余參數(shù)是ES6提供的共螺,并且希望以此替代arguments

剩余參數(shù)必須是 函數(shù)的參數(shù)的最后一個位置,否則會報錯情竹。

function foo(m,n,...args){
  console.log(m,n);//10 20
  console.log(args); //[ 30, 40, 50, 60, 70 ]
}

foo(10,20,30,40,50,60,70)
function bar(...args,m,n){ //*Rest parameter must be last formal parameter
  console.log(args);
  console.log(m);
  console.log(n);
}
bar(1,2,3,4)

8.函數(shù)箭頭函數(shù)的補充

  • 箭頭函數(shù)是沒有顯式原型的藐不,所以不能作為構(gòu)造函數(shù)
  • 箭頭函數(shù)沒有this,箭頭函數(shù)的this會去上層作用域查找,如果還沒有找到雏蛮,會繼續(xù)往上查找涎嚼。直到全局作用域中
  • 箭頭函數(shù)沒有arguments
var bar=()=>{
  
}
console.log(bar.prototype);//undefined
console.log(new bar());//* bar is not a constructor

9.展開語法(Spread syntax)

  • 可以在函數(shù)調(diào)用/數(shù)組構(gòu)造時,將數(shù)組表達(dá)式或者string在語法層面展開
  • 還可以在構(gòu)造字面量對象時挑秉,將對象表達(dá)式按key-value的方式展開
const names=["abc","wjy","nba"];

// * 1.函數(shù)調(diào)用時
function foo(x,y,z){
  console.log(x,y,z);
}
foo.apply(null,names);//這種方式也可以法梯,但是閱讀性非常差
foo(...names)
let str="wjy";
foo(...str)

// * 2.構(gòu)造數(shù)組時
const newNames=[...names]

//*  3. ES2018 (ES9)構(gòu)造 字面量對象
let info={
  name:"wjy",
  age:20,
  height:160
}
let newInfo={...info,...names}; //* 數(shù)組展開在對象中,key是對應(yīng)的索引值
console.log(newInfo);

// * 展開運算符其實是一個淺拷貝

9.1 展開運算符的淺拷貝

const info={
  name:"wjy",
  friend:{
    name:"kobe"
  }
}
// * 淺拷貝的是拷貝的對象的第一層屬性的值犀概,如果拷貝的對象的屬性的值引用類型立哑,其實在拷貝的對象中對應(yīng)的屬性的引用的是同一片內(nèi)存空間
const newInfo={...info}
newInfo.friend.name="hyz"
console.log(info);

10.數(shù)值的表示

在ES6中規(guī)范了二進制和八進制的寫法:

  • 二進制:以0b開頭
  • 八進制:以0O開頭
  • 十六進制:以0x開頭
let num1=100;//默認(rèn)是10進制
let num2=0b100;//二進制
let num3=0O100;//八進制
let num4=0x100;//十六進制

console.log(num1,num2,num3,num4);//100 4 64 256


// * 大的數(shù)值(在ES2021 ES12中),允許使用下劃線進行連接
// const num=10000000000;//這種可讀性非常差
const num=10_000_000_000;
console.log(num);

11.Symbol的基本使用

Symbol是ES6新增的一個基本的數(shù)據(jù)類型,翻譯為符號姻灶。

那么為什么需要Symbol呢刁憋?

  • 在ES6之前,對象的屬性都是字符串形式木蹬,那么很容易造成屬性名的沖突
  • 比如原來有一個對象至耻,我們希望在其中添加一個新的屬性和值,但是在我們不確定它原來內(nèi)部有什么內(nèi)容的情況下镊叁,很容易造成沖突尘颓,從而覆蓋它內(nèi)部的某個屬性
  • 比如我們前面實現(xiàn)講apply、call晦譬、bind實現(xiàn)時疤苹,我們給其中添加一個fn屬性,那么如果它內(nèi)部原來有一個fn屬性了呢敛腌?
  • 如果在開發(fā)中我們使用了混入卧土,那么混入中出現(xiàn)了同名的屬性,必然有一個會被覆蓋掉像樊。

Symbol就是為了解決上面的問題尤莺,用來生成一個獨一無二的值

  • Symbol的值是通過Symbol函數(shù)來生成的,生成后可以作為屬性名
  • 也就是在ES6中生棍,對象的屬性名就可以使用字符串颤霎,也可以使用Symbol值

Symbol即使多次創(chuàng)建值,它們也是不同的:Symbol函數(shù)每次創(chuàng)建出來的值都是獨一無二的

我們也可以在創(chuàng)建Symbol值的時候傳入一個描述description:這個是ES2019(ES10)新增的特性

11.1 Symbol作為屬性名

// * 3.Symbol作為key
// * 寫法1
const obj2={
  [s1]:"abc",
  [s2]:"wjy"
}
console.log(obj2);

// * 新增:ES2019 ES10新增可以向Symbol傳入一個description
obj2[s3]="hyz"
console.log(obj2);

// * 新增
Object.defineProperty(obj2,Symbol("s4"),{
  value:"s4",
  configurable:true,
  enumerable:true,
  writable:true
})

// * 獲取:只能通過[]獲取涂滴,不能通過.語法獲取
console.log(obj2[s1]);
console.log(obj2.s1);//* undefined 這樣是獲取不到的友酱,因為通過.獲取的時候,會根據(jù)后面的名字去對象找對象的屬性名為這個的值
// * 4.使用Symbol作為key柔纵,在遍歷/Object.keys是獲取不到Symbol屬性值的
// * 需要通過Object.getOwnPropertySymbols來獲取所有的Symbol的key
console.log(Object.keys(obj2));//[]
console.log(Object.getOwnPropertyNames(obj2));//[]
console.log(Object.getOwnPropertySymbols(obj2));//[ Symbol(), Symbol(), Symbol(hyz), Symbol(s4) ]

let sKeys=Object.getOwnPropertySymbols(obj2)

for(const item of sKeys ){
  console.log(obj2[item]);
}

11.2 相同的key生成相同的Symbol

如果想根據(jù)相同的key創(chuàng)建相同的Symbol可以使用Symbol.for(key)

可以通過Symbol.keyFor獲取對應(yīng)的key

// * 5. Symbol.for(key) :如果想要創(chuàng)建一樣的Symbol值:通過相同的key創(chuàng)建相同的Symbol
const sa=Symbol.for("aaa");
const sb=Symbol.for("aaa");
console.log(sa==sb);//true

// * 獲取key
const key=Symbol.keyFor(sa);
console.log(key);

12.總結(jié)

ES6知識點詳解.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末缔杉,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子搁料,更是在濱河造成了極大的恐慌或详,老刑警劉巖进苍,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鸭叙,居然都是意外死亡觉啊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進店門沈贝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杠人,“玉大人,你說我怎么就攤上這事宋下∥松疲” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵学歧,是天一觀的道長罩引。 經(jīng)常有香客問我,道長枝笨,這世上最難降的妖魔是什么袁铐? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮横浑,結(jié)果婚禮上剔桨,老公的妹妹穿的比我還像新娘。我一直安慰自己徙融,他們只是感情好洒缀,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著欺冀,像睡著了一般树绩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上隐轩,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天饺饭,我揣著相機與錄音,去河邊找鬼龙助。 笑死砰奕,一個胖子當(dāng)著我的面吹牛蛛芥,可吹牛的內(nèi)容都是我干的提鸟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼仅淑,長吁一口氣:“原來是場噩夢啊……” “哼称勋!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起涯竟,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤赡鲜,失蹤者是張志新(化名)和其女友劉穎空厌,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體银酬,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡嘲更,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了揩瞪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赋朦。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖李破,靈堂內(nèi)的尸體忽然破棺而出宠哄,到底是詐尸還是另有隱情,我是刑警寧澤嗤攻,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布毛嫉,位于F島的核電站,受9級特大地震影響妇菱,放射性物質(zhì)發(fā)生泄漏承粤。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一闯团、第九天 我趴在偏房一處隱蔽的房頂上張望密任。 院中可真熱鬧,春花似錦偷俭、人聲如沸浪讳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽淹遵。三九已至,卻和暖如春负溪,著一層夾襖步出監(jiān)牢的瞬間透揣,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工川抡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辐真,地道東北人。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓崖堤,卻偏偏與公主長得像侍咱,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子密幔,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

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