ES6

1.變量聲明let和const

預(yù)解析機制 : var有變量提升的機制

function fn(){
    var a=1
    console.log(a)
}
fn()  //1

//以上代碼等同于:
function fn(){
    var a
    a=1
    console.log(a)
}
fn()  //1

把聲明賦值和打印的語句順序交換

function fn(){
    console.log(a)
    var a=1
}
fn()  //undefined

//以上代碼等同于:
function fn(){
    var a
    console.log(a)
    a=1
}
fn()  //undefined

ES5的解析:從上到下解析,遇到var關(guān)鍵字,就把該聲明提前到函數(shù)的最頂部,如果不在函數(shù)內(nèi)就提升到全局作用域的最頂部,賦值留在原位,因為先聲明了變量a,然后打印,最后再賦值,所以結(jié)果就是undefined。
但是使用letconst就可以解決變量提升的問題,let代表變量,const代表常量。

let

function fn(){
    let a=1
    console.log(a)
}
fn()  //1

把聲明賦值和打印的語句順序交換

function fn(){
    console.log(a)
    let a=1
}
fn()  //Error: a is not defined

let不存在變量提升的機制,不會被聲明到最頂部,所以未聲明就打印,會報錯:變量未定義。

const

const PI=3.14
PI=3.1415926  //Error: Assignment to constant variable.

const的聲明必須賦值,賦值之后不可修改。那要怎么修改const的值呢?
實際上是const的指向不可修改,但是可以通過更改地址中的內(nèi)容來修改了const的值。

const stu={ name: '小明' }
//正確,改變地址中的內(nèi)容
stu.name='小紅'
//報錯,改變了const的指向
stu={ name: '小紅' }

TDZ(暫時性死區(qū))

if (true) {
  // TDZ開始
    tmp = 'abc';
    console.log(tmp); // Error: tmp is not defined
    
    let tmp; // TDZ結(jié)束
    console.log(tmp); // undefined

    tmp = 123;
    console.log(tmp); // 123
}

let 或者 const,會將聲明放入TDZ(暫時性死區(qū)),只有執(zhí)行到變量聲明語句時,變量才會從TDZ中取出來使用??傊?,暫時性死區(qū)的本質(zhì)就是,只要一進入當(dāng)前作用域,所要使用的變量就已經(jīng)存在了,但是不可獲取,只有等到聲明變量的那一行代碼出現(xiàn),才可以獲取和使用該變量。

塊級作用域

ES6在ES5 全局作用域和函數(shù)作用域的基礎(chǔ)上開拓了塊級作用域,使得變量的作用域更加清晰。

內(nèi)層變量覆蓋外層變量

var tmp = new Date();

function f() {
  console.log(tmp);
  var tmp = 'hello world';
}

f(); // undefined

函數(shù)f執(zhí)行后,輸出結(jié)果為undefined,原因在于變量提升,導(dǎo)致內(nèi)層的tmp變量覆蓋了外層的tmp變量。

用來計數(shù)的循環(huán)變量泄露為全局變量

var s = 'hello';

for (var i = 0; i < s.length; i++) {
  console.log(s[i]);
}

console.log(i); // 5

變量i只用來控制循環(huán),但是循環(huán)結(jié)束后,它并沒有消失,泄露成了全局變量。

ES6新增了塊級作用域,即一個{}就是一個塊級作用域。

{ let a=1 }
console.log(a)  //報錯

不同塊級作用域可以定義重名的變量

{
  let a='hello world'
  { let a='hello world' }
}

立即執(zhí)行函數(shù)就可以用塊級作用域來替代

//  IIFE寫法
(function(){
    var a=...
    ...
})()

//  塊級作用域?qū)懛?{
    var a=...
    ...
}

2.變量的解構(gòu)賦值

數(shù)組的解構(gòu)賦值

解構(gòu)賦值語法是一個Javascript表達式,這使得可以將數(shù)據(jù)從數(shù)組或?qū)ο筇崛〉讲煌淖兞恐小?/p>

以前為變量賦值,只能直接指定值。

let a = 1
let b = 2
let c = 3

ES6就可以寫成這樣

let [a, b, c] = [1, 2, 3]

本質(zhì)是上述匹配屬于一種模式匹配, 也就是只要等號兩邊的模式相同,左邊的變量就會被賦予對應(yīng)的值。

let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3

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

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

let [bar, foo] = [1];
bar //1
foo //undefined

默認值

解構(gòu)賦值允許指定默認值

let [ a = 1 ]= [ ]
a //1

ES6 內(nèi)部使用嚴格相等運算符(===),判斷一個位置是否有值。所以,只有當(dāng)一個數(shù)組成員嚴格等于undefined,默認值才會生效。

let [x = 1] = [undefined];
x // 1

let [x = 1] = [null];
x // null

null不嚴格等于undefined,默認值不生效。
如果默認值是一個表達式,表示則是惰性求值的,只有在用到的時候才會求值。

function fn(){
    return -1
}
let [a = fn()]=[]
console.log(a)  //-1
let [b = fn()]=[1]
console.log(b)  //1

默認值可以引用其他變量,但該變量必須已經(jīng)聲明。

let [x = 1, y = x] = []     // x=1; y=1
let [x = 1, y = x] = [2]   // x=2; y=2
let [x = 1, y = x] = [1, 2] // x=1; y=2
let [x = y, y = 1] = []   // Error: y is not defined

xy做默認值,但是y還沒有聲明,所以報錯。

對象的解構(gòu)賦值

解構(gòu)不僅可以用于數(shù)組,還可以用于對象。
對象的解構(gòu)賦值與數(shù)組不同的是:數(shù)組的元素是按次序排列的,變量的取值由它的位置決定;而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值。

var {foo,bar} = {foo: 'aaa', bar: 'bbb'}
console.log(foo)  //aaa
console.log(bar)  //bbb
//以上代碼等同于:
let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" }
var {baz} = {foo: 'aaa', bar: 'bbb'}
console.log(baz)  //undefined

以上未找到baz,解構(gòu)賦值失敗。

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

foo是匹配的模式,baz才是變量。真正被賦值的是變量baz,而不是模式foo。

let obj = {
  p: [
    'hello',
    { y: 'world' }
  ]
}
let { p: [x, { y }] } = obj
 console.log(x,y)  //hello word

字符串的解構(gòu)賦值

字符串的解構(gòu)賦值,符串會轉(zhuǎn)化成一個類數(shù)組的對象。

const [a,b,c,d,e] = 'hello'     
console.log(a,b,c,d,e)  //h e l l o

類數(shù)組對象有length屬性,所以len是5。

let {length : len} = 'hello';
len  //5

函數(shù)參數(shù)的解構(gòu)賦值

函數(shù)的參數(shù)也可以使用解構(gòu)賦值

function add([x, y]){
  return x + y;
}
add([1, 2]); // 3

3.字符串的擴展

  • 模板字符串

拼接字符串一直是令人頭痛的地方,一旦變量多起來,字符串的拼接就會變得尤為繁瑣,而且可讀性極低,模板字符串簡直就是開發(fā)者的福音。用${}嵌入字符串中拼接,有幾個變量就用幾個${}

// es5
var name='world'
console.log('hello'+name)

//es6
var name='world'
console.log(`hello${name}`)
  • 在ES5中通過反斜杠(\)來做多行字符串的拼接,ES6反引號(``)可以直接搞定。
// es5
var msg='hello \
world!'

// es6
const template=`
  <div>
    <span>hello world!</span>
  </div>
`
  • 對運算的支持
let a=1
let b=2
let result=`${a+b}`
console.log(result)  //3
  • 字符串是否存在
// es5
let name = 'Github'
let msg = 'hello world,my name is Github'
console.log(msg.indexOf(name))  //返回索引值

// es6
let name = 'Github'
let msg = 'hello world,my name is Github'
console.log(msg.includes(name))  //返回布爾值,更直觀
  • 復(fù)制字符串
console.log('hello world|'.repeat(3))  // hello world|hello world|hello world|

4.箭頭函數(shù)

ES6提供了箭頭函數(shù),給函數(shù)的創(chuàng)建提供了一種簡便方法。
三大特點:
省略function關(guān)鍵字
省略return關(guān)鍵字
繼承當(dāng)前上下文的this關(guān)鍵字

// es5
[1,2,3].forEach((function (item) {
  return item + 1
}).bind(this))

// es6
[1,2,3].forEach(item=>item+=1)

當(dāng)參數(shù)只有一個時,可以省略(),當(dāng)函數(shù)表達式只有一個時,可以省略{}return

//  一個參數(shù),一個表達式
let person = name => 'hello ' + name
console.log(person('world'))  //hello world

// 多個參數(shù),多個表達式
let person = (name,age) => {
  const msg = `hello ${name},age is ${age}`
  return msg 
}
console.log(person('world',18))  //hello world,age is18

在使用別人的輪子時,因為不熟練經(jīng)常會報錯,那么這些框架是怎么拋出錯誤的呢?

let add = (a,b=1) =>{
  if(a<=0){
    throw new Error('The variable must be greater than 0')
  }
  return a+b
}
console.log(add(0));  // Uncaught Error: The variable must be greater than 0

5.對象擴展功能

  • 在對象的鍵值對重名時,可以這樣處理
// es5
function person(name,age){
  return {
    name:name,
    age:age
  } 
}

// es6
function person(name,age){
  return {
    name,
    age
  }
}
  • ES6改進了為對象字面量方法賦值的語法,可以省略:function關(guān)鍵字
// es5
function person(name){
  name,
  sayHi:function(){
    console.log('Hi')
  }
}

// es6
function person(name){
  name,
  sayHi(){
    console.log('Hi')
  }
}
  • 合并對象
let obj1={name:'Github'}
let obj2={sex:'男'}
let obj3={age:18}

let obj = Object.assign({},obj1,obj2,obj3)
console.log(obj)  // {name:"Github",sex:"男",age:18}

6.擴展運算符(...)

  • 組裝數(shù)組或者對象
const arr1=[1,2,3]
const arr2=[...arr1,4,5,6]
console.log(arr2)  //[1,2,3,4,5,6]

const obj1={
    a:1,
    b:2
}
const obj2={...obj1,c:3,d:4}
console.log(obj2); //{a:1,b:2,c:3,d:4}

7.promise

在promise之前,回調(diào)地獄,可讀性差、耦合度高、擴展性低 。promise大大提高了代碼的可讀性,用同步編程的方式來編寫異步代碼,極大的降低了代碼耦合性而提高了程序的可擴展性。

promise執(zhí)行多步操作非常好用,現(xiàn)在模仿一個多步操作的過程。
把大象裝進冰箱需要幾步?答:三步,打開冰箱門,把大象塞進去,關(guān)上冰箱門。

let flag = true;
function step1(resolve, reject) {
    console.log('1.開始-打開冰箱門');
    if (flag) {
        resolve('打開冰箱門--完成');
    } else {
        reject('打開冰箱門--出錯');
    }
}
function step2(resolve, reject) {
    console.log('2.開始-把大象塞進去');
    if (flag) {
        resolve('把大象塞進去--完成');
    } else {
        reject('把大象塞進去--出錯');
    }
}
function step3(resolve, reject) {
    console.log('3.開始-關(guān)上冰箱門');
    if (flag) {
        resolve('關(guān)上冰箱門--完成');
    } else {
        reject('關(guān)上冰箱門--出錯');
    }
}
new Promise(step1).then(function (val) {
    console.log(val);
    return new Promise(step2);
}).then(function (val) {
    console.log(val);
    return new Promise(step3);
}).then(function (val) {
    console.log(val);
    return val;
});
/* 
1.開始-打開冰箱門
打開冰箱門--完成
2.開始-把大象塞進去
把大象塞進去--完成
3.開始-關(guān)上冰箱門
關(guān)上冰箱門--完成
*/

8.class類

class聲明和使用

// 類的聲明
class Coder{
    getName(name){
        console.log(name);
    }
}
// 類的使用
let Github=new Coder
Github.getName('Github')  // Github

聲明一個JsCoder的新類并繼承Coder類

class Coder{
    getName(name){
        console.log(name);
    }
}

class JsCoder extends Coder{}

let js=new JsCoder
js.getName('js')

9.模塊化

前后端分離,前端業(yè)務(wù)邏輯也在日益復(fù)雜,前端也在借鑒后端的思想,ES6為我們增加了模塊化操作來方便我們引用第三方庫,尤其是在開發(fā)vue項目時,需要依賴大量第三方包,需要我們使用到模塊化的思想來開發(fā)項目。

  • import : 引入模塊
  • export : 輸出模塊
// a.js 導(dǎo)出
export var name='hello world'
export function add(a,b){
    return a+b;
}

// b.js 導(dǎo)入
import { name,add } from "./a.js"  //也可以分開導(dǎo)入
console.log(name)  //hello world
console.log(add(1,2))  //3

總結(jié)

ES6的內(nèi)容遠不止這些,不過也算是高頻使用了,更多內(nèi)容可以去看一下阮大神的ES6在線書籍。對于即將入門vue的小伙伴來說,ES6的學(xué)習(xí)對你來說是必不可少的,ES6的語法為我們前端開發(fā)者提供了更多的便利,也是學(xué)習(xí)vue框架的一塊敲門磚,祝大家能盡快地掌握ES6語法,提高開發(fā)效率,本人也是剛學(xué)習(xí)ES6不久,如果文中內(nèi)容有誤,請不要吝嗇您的意見或建議,歡迎留評。

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

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

  • [TOC] 參考阮一峰的ECMAScript 6 入門參考深入淺出ES6 let和const let和const都...
    郭子web閱讀 1,913評論 0 1
  • 一、ES6簡介 ? 歷時將近6年的時間來制定的新 ECMAScript 標準 ECMAScript 6(亦稱 ...
    一歲一枯榮_閱讀 6,206評論 8 25
  • ? 何為ES6語法糖?即這些事情ES5也可以做,只是稍微復(fù)雜一些,而ES6提供了非破壞性的更新, 目的是提供更簡潔...
    果汁涼茶丶閱讀 1,389評論 0 4
  • 最有啟發(fā)的一點:技能是用來幫助別人的,不是用來炫耀的。我好像會犯這個毛病,而且經(jīng)常,知道點什么就巴不得說出來。所以...
    梨子瘦了閱讀 146評論 5 2
  • 寫給喬任梁的100信 第1封你獨自去旅行,我們沒有再見也沒有告別。 第2封你走了,我的城市開始下雨,我的世界里從此...
    煙雨墨痕521閱讀 1,090評論 0 2

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