ES6 快速入门
ES6 快速入門
1.變量聲明let和const
1)在ES6以前,var關鍵字聲明變量,無論聲明在何處,都會被視為聲明在全局作用域的最頂部。這就是函數變量提升:
function aa() {if(bool) {var test = 'hello man'} else {console.log(test)}}實際上是:
function aa() {var test // 變量提升if(bool) {test = 'hello man'} else {//此處訪問test 值為undefinedconsole.log(test)}//此處訪問test 值為undefined}所以不用關心bool是否為true or false。實際上,無論如何test都會被創建聲明。
我們通常用let和const來聲明,let表示變量、const表示常量。let和const都是塊級作用域。怎么理解這個塊級作用域?
- 在一個函數內部
- 在一個代碼塊內部
說白了?{}大括號內的代碼塊即為let 和 const的作用域。
以下代碼:
function aa() {if(bool) {let test = 'hello man'} else {//test 在此處訪問不到console.log(test)}}let的作用域是在它所在當前代碼塊,但不會被提升到當前函數的最頂部。
2)const
const name = 'lux'name = 'joe' //再次賦值此時會報錯eg:
var funcs = []for (var i = 0; i < 10; i++) {funcs.push(function() {console.log(i)
})}funcs.forEach(function(func) {func()})
輸出 10 十次,但是如果我們想依次輸出0到9呢?兩種解決方法:
// ES5告訴我們可以利用閉包解決這個問題var funcs = []for (var i = 0; i < 10; i++) {func.push((function(value) {return function() {console.log(value)}}(i)))}// es6for (let i = 0; i < 10; i++) {func.push(function() {console.log(i)})}2.模板字符串
1)基本的字符串格式化。將表達式嵌入字符串中進行拼接。用${}來界定。
//es5 var name = 'lux'console.log('hello' + name)//es6const name = 'lux'console.log(`hello ${name}`) //hello lux2)在ES5時我們通過反斜杠(\)來做多行字符串或者字符串一行行拼接。ES6反引號(``)直接搞定。
// es5var msg = "Hi \man!"// es6const template = `<div><span>hello world</span></div>`3)對于字符串es6當然也提供了很多方法:
// 1.includes:判斷是否包含然后直接返回布爾值let str = 'hahay'console.log(str.includes('y')) // true// 2.repeat: 獲取字符串重復n次let s = 'he'console.log(s.repeat(3)) // 'hehehe'//如果你帶入小數, Math.floor(num) 來處理3.函數
1)函數默認參數
在ES5我們給函數定義參數默認值:
function action(num) {num = num || 200//當傳入num時,num為傳入的值//當沒傳入參數時,num即有了默認值200return num}但num傳入為0的時候就是false, 此時num = 200 與我們的實際要的效果明顯不一樣
ES6為參數提供了默認值。在定義函數時便初始化了這個參數,以便在參數沒有被傳遞進去時使用。
function action(num = 200) {console.log(num)}action() //200action(300) //3002)箭頭函數
ES6很有意思的一部分就是函數的快捷寫法。也就是箭頭函數。
箭頭函數最直觀的三個特點。
- 不需要function關鍵字來創建函數
- 省略return關鍵字
- 繼承當前上下文的 this 關鍵字
當你的函數有且僅有一個參數的時候,是可以省略掉括號的。當你函數返回有且僅有一個表達式的時候可以省略{};例如:
var people = name => 'hello' + name//參數name就沒有括號參考:
var people = (name, age) => {const fullName = 'h' + namereturn fullName} //如果缺少()或者{}就會報錯4.拓展的對象功能
1)對象初始化簡寫
ES5我們對于對象都是以鍵值對的形式書寫,是有可能出現鍵值對重名的。例如:
function people(name, age) {return {name: name,age: age};}鍵值對重名,ES6可以簡寫如下:
function people(name, age) {return {name,age};}2)ES6 同樣改進了為對象字面量方法賦值的語法。ES5為對象添加方法:
const people = {name: 'lux',getName: function() {console.log(this.name)}}ES6通過省略冒號與 function 關鍵字,將這個語法變得更簡潔
const people = {name: 'lux',getName () {console.log(this.name)}}3)ES6 對象提供了Object.assign()這個方法來實現淺復制。Object.assign()可以把任意多個源對象自身可枚舉的屬性拷貝給目標對象,然后返回目標對象。第一參數即為目標對象。在實際項目中,我們為了不改變源對象。一般會把目標對象傳為{}
const obj = Object.assign({}, objA, objB)5.更方便的數據訪問
1)數組和對象是JS中最常用也是最重要表示形式。為了簡化提取信息,ES6新增了解構,這是將一個數據結構分解為更小的部分的過程
ES5我們提取對象中的信息形式如下:
const people = {name: 'lux',age: 20}const name = people.nameconst age = people.ageconsole.log(name + ' --- ' + age)解構能讓我們從對象或者數組里取出數據存為變量,例如
//對象const people = {name: 'lux',age: 20}const { name, age } = peopleconsole.log(`${name} --- ${age}`)//數組const color = ['red', 'blue']const [first, second] = colorconsole.log(first) //'red'console.log(second) //'blue'6.Spread Operator 展開運算符
S6中另外一個好玩的特性就是Spread Operator 也是三個點兒(...)
1)組裝對象或者數組
//數組const color = ['red', 'yellow']const colorful = [...color, 'green', 'pink']console.log(colorful) //[red, yellow, green, pink]//對象const alp = { fist: 'a', second: 'b'}const alphabets = { ...alp, third: 'c' }console.log(alphabets) //{ "fist": "a", "second": "b", "third": "c" }獲取數組或者對象除了前幾項或者除了某幾項的其他項
const number = [1,2,3,4,5]const [first, ...rest] = numberconsole.log(rest) //2,3,4,5//對象const user = {username: 'lux',gender: 'female',age: 19,address: 'peking'}const { username, ...rest } = userconsole.log(rest) //{"address": "peking", "age": 19, "gender": "female" }2)對于 Object 而言,還可以用于組合成新的 Object 。如果有重復的屬性名,右邊覆蓋左邊
const first = {a: 1,b: 2,c: 6,}const second = {c: 3,d: 4}const total = { ...first, ...second }console.log(total) // { a: 1, b: 2, c: 3, d: 4 }7.import 和 export
1)import導入模塊、export導出模塊
//全部導入 import people from './example'//有一種特殊情況,即允許你將整個模塊當作單一對象進行導入 //該模塊的所有導出都會作為對象的屬性存在 import * as example from "./example.js" console.log(example.name) console.log(example.age) console.log(example.getName())//導入部分 import {name, age} from './example'// 導出默認, 有且只有一個默認 export default App// 部分導出 export class App extend Component {};導入的時候有沒有大括號的區別:
1.當用export default people導出時,就用 import people 導入(不帶大括號)2.一個文件里,有且只能有一個export default。但可以有多個export。3.當用export name 時,就用import { name }導入(記得帶上大括號)4.當一個文件里,既有一個export default people, 又有多個export name 或者 export age時,導入就用 import people, { name, age } 5.當一個文件里出現n多個 export 導出很多模塊,導入時除了一個一個導入,也可以用import * as example8. Promise
在promise之前代碼過多的回調或者嵌套,可讀性差、耦合度高、擴展性低。通過Promise機制,扁平化的代碼機構,大大提高了代碼可讀性;用同步編程的方式來編寫異步代碼,保存線性的代碼邏輯,極大的降低了代碼耦合性而提高了程序的可擴展性。
用同步的方式去寫異步代碼。
1)發起異步請求
fetch('/api/todos').then(res => res.json()).then(data => ({ data })).catch(err => ({ err }));eg:
setTimeout(function() {console.log(1)}, 0);new Promise(function executor(resolve) {console.log(2);for( var i=0 ; i<10000 ; i++ ) {i == 9999 && resolve();}console.log(3);}).then(function() {console.log(4);});console.log(5);9.Generators
生成器( generator)是能返回一個迭代器的函數。生成器函數也是一種函數,最直觀的表現就是比普通的function多了個星號*,在其函數體內可以使用yield關鍵字,有意思的是函數會在每個yield后暫停。
這里生活中有一個比較形象的例子。咱們到銀行辦理業務時候都得向大廳的機器取一張排隊號。你拿到你的排隊號,機器并不會自動為你再出下一張票。也就是說取票機“暫?!弊×?#xff0c;直到下一個人再次喚起才會繼續吐票。
OK。說說迭代器。當你調用一個generator時,它將返回一個迭代器對象。這個迭代器對象擁有一個叫做next的方法來幫助你重啟generator函數并得到下一個值。next方法不僅返回值,它返回的對象具有兩個屬性:done和value。value是你獲得的值,done用來表明你的generator是否已經停止提供值。繼續用剛剛取票的例子,每張排隊號就是這里的value,打印票的紙是否用完就這是這里的done。
// 生成器function *createIterator() {yield 1;yield 2;yield 3;}// 生成器能像正規函數那樣被調用,但會返回一個迭代器let iterator = createIterator();console.log(iterator.next().value); // 1console.log(iterator.next().value); // 2console.log(iterator.next().value); // 3那生成器和迭代器的用處
圍繞著生成器的許多興奮點都與異步編程直接相關。異步調用對于我們來說是很困難的事,我們的函數并不會等待異步調用完再執行,你可能會想到用回調函數,(當然還有其他方案比如Promise比如Async/await)。
生成器可以讓我們的代碼進行等待。就不用嵌套的回調函數。使用generator可以確保當異步調用在我們的generator函數運行一下行代碼之前完成時暫停函數的執行。
因為不能手動一直調用next()方法,所以需要一個能夠調用生成器并啟動迭代器的方法。就像這樣子的
function run(taskDef) { //taskDef即一個生成器函數// 創建迭代器,讓它在別處可用let task = taskDef();// 啟動任務let result = task.next();// 遞歸使用函數來保持對 next() 的調用function step() {// 如果還有更多要做的if (!result.done) {result = task.next();step();}}// 開始處理過程step();}生成器與迭代器最有趣、最令人激動的方面,或許就是可創建外觀清晰的異步操作代碼。你不必到處使用回調函數,而是可以建立貌似同步的代碼,但實際上卻使用 yield 來等待異步操作結束。
轉載于:https://www.cnblogs.com/Michelle20180227/p/8527521.html
總結
- 上一篇: 在Windows QT下使用ZeroMQ
- 下一篇: 【Java面试题】3 Java中使用fi