1、ES6快速入門
let和const
let
ES6新增了let命令,用於聲明變量。其用法相似var,可是聲明的變量只在let命令所在的代碼塊內有效。react
![](http://static.javashuo.com/static/loading.gif)
效果以下:git
var聲明變量存在變量提高。也就是在聲明變量以前就可使用該變量。es6
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,粘貼代碼,效果以下:github
而let不會這樣,let聲明的變量不能在聲明以前使用。面試
刷新頁面,粘貼代碼,效果以下:ajax
好比:typescript
function foo(){ let x = 10; var x = 20; } foo(); // 報錯
刷新頁面,粘貼代碼,效果以下:
再好比:
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,粘貼代碼,效果以下:
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,粘貼代碼,效果以下:
![](http://static.javashuo.com/static/loading.gif)
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,粘貼代碼,效果以下:
var聲明的變量會污染全局,因此在for循環外部能夠打印i的值。for循環中的i最好使用let聲明
ES6中的let聲明變量的方式實際上就爲JavaScript新增了塊級做用域。
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,粘貼代碼,效果以下:
此時,在foo函數內容,外層代碼塊就再也不受內層代碼塊的影響。因此相似for循環的計數變量咱們最好都是用let來聲明。
let聲明可以將變量限制在當前的塊級做用域中
const
const用來聲明常量。const聲明變量必須當即初始化,而且其值不能改變。
const聲明常量的做用域與let相同,只在生命所在的塊級做用於內有效
const PI = 3.14;
舉例:
const 用來聲明一個常量,不能修改
全局對象的屬性:
ES6規定:var命令和function命令聲明的全局變量依舊是全局對象的屬性;let命令、const命令和class命令聲明的全局變量不屬於全局對象的屬性。
查看下面的示例代碼:
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,粘貼代碼,效果以下:
變量的解構賦值
ES6容許按照必定的模式,從數組或對象中提取值,對變量進行賦值,這種方式被成爲解構賦值
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,粘貼代碼,效果以下:
對象的解構賦值:
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,粘貼代碼,效果以下:
var和function聲明的變量,默認會在windows對象上
let聲明的變量默認不會出如今windows對象上
舉例:
window.name1輸出undefined
函數
箭頭函數
箭頭函數特色:
1.若是參數只有一個,能夠省略小括號
2.若是不寫return,能夠不屑大括號
3.沒有arguments
4.不改變this指向
其中箭頭函數中this指向被固定化,不是由於箭頭函數內部有綁定this的機制。實際緣由是箭頭函數根本沒有本身的this,致使內部的this就是外層代碼塊的this
能夠查看下面兩段代碼輸出的區別:
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,粘貼代碼,效果以下:
和
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,粘貼代碼,效果以下:
但凡用到箭頭函數,不要用this
對象
屬性簡潔表示法
ES6容許直接寫入變量和函數做爲對象的屬性和方法。
![](http://static.javashuo.com/static/loading.gif)
上面的寫法等同於:
![](http://static.javashuo.com/static/loading.gif)
對象的方法也可使用簡潔表示法:
![](http://static.javashuo.com/static/loading.gif)
等同於:
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,粘貼代碼,效果以下:
Object.assign()
Object.assign方法用來將源對象(source)的全部可枚舉屬性複製到目標對象(target)。它至少須要兩個對象做爲參數,第一個參數是目標對象,第二個參數是源對象。
參數必須都是對象,不然拋出TypeError錯誤。
Object.assjgn只複製自身屬性,不可枚舉屬性(enumerable爲false)和繼承的屬性不會被複制。
簡單示例:
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,粘貼代碼,效果以下:
注意:
Object.assign方法的其餘用處,可查看文末連接。
面向對象:類
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,效果以下:
ES6 使用Class構造對象的方式:
修改test.html,js代碼以下:
![](http://static.javashuo.com/static/loading.gif)
刷新頁面,效果以下:
2、Vue
一、vue的介紹
(1)前端三大框架
(能夠去github查看三個框架的 star星):
vue 尤雨溪,漸進式的JavaScript框架
react Facebook公司,裏面的(高階函數 es6)很是多,對初學者不友好
angular 谷歌公司,目前更新到6.0,學習angular得須要玩一下typescript
(2)cdn方式引用
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
(3)下載到本地引用
<script src='./vue.js'></script>
(4)庫和框架
上面vue.js文件是一個庫,小而精;
框架是功能比較齊全,像Django,大而全,功能比較多;
(5)實例化對象
示例代碼:
![](http://static.javashuo.com/static/loading.gif)
注意:若是是咱們本身定義的屬性和方法,則所有暴露在外面,若是是vue實例對象本身屬性和方法,會在前邊加一個」$」進行區分。另外,data中有一個觀察者Observer,在觀察着一些數據是否發生了改變,若改變,則將改變後的值立馬渲染到DOM中對應的地方,控制檯查看data效果以下圖:
二、vue的模板語法
<div id="app"> <!--模板語法--> <h2>{{ msg1 }}</h2> <h3>{{ 'haha' }}</h3> <h3>{{ 1+1 }}</h3> <h4>{{ {'name':'alex'} }}</h4> <h5>{{ person.name }}</h5> <h2>{{ 1>2?'真的':'假的' }}</h2> <p>{{ msg2.split('').reverse().join('') }}</p> </div>
三、vue的思想:
數據驅動視圖,設計模式MVVM(model view viewmodel)
四、vue的基本指令
(使用指令系統後邊必定是字符串,且字符串中的變量必定是數據屬性中已有的變量)
(1)vue的指令系統之v-text和v-html(***),以下:
![](http://static.javashuo.com/static/loading.gif)
效果以下圖:
(2)條件渲染v-if和v-show,以下:效果以下圖:
<div class="box1" v-show="isShow">hello</div> <div class="box2" v-if="isShow">hello</div>
分析:isShow爲真則顯示div,爲假則不顯示;
區別:v-show爲假時至關於display:none;v-if爲假時至關於移除該div,可是有一個佔位的註釋」<!-- -->」;
官網對v-if和v-show的區別:
1)v-if 是「真正」的條件渲染,由於它會確保在切換過程當中條件塊內的事件監聽器和子組件適當地被銷燬和重建。
2)v-if 也是惰性的:若是在初始渲染時條件爲假,則什麼也不作——直到條件第一次變爲真時,纔會開始渲染條件塊。
3)相比之下,v-show 就簡單得多——無論初始條件是什麼,元素老是會被渲染,而且只是簡單地基於 CSS 進行切換。
4)通常來講,v-if 有更高的切換開銷,而 v-show 有更高的初始渲染開銷。所以,若是須要很是頻繁地切換,則使用 v-show 較好;若是在運行時條件不多改變,則使用 v-if 較好。
v-if與v-else:可使用 v-else 指令來表示 v-if 的「else 塊」:
<div v-if="Math.random() > 0.5"> Now you see me </div> <div v-else> Now you don't </div> // 注意:v-else 元素必須緊跟在帶 v-if 或者 v-else-if 的元素的後面,不然它將不會被識別。
(3)v-bind和v-on
v-bind:標籤中全部屬性,如img標籤的src alt,a標籤的href title id class等,以下:
<img v-bind:src="imgSrc" v-bind:alt="msg">
v-bind:class='{active:isActive}'表示若isActive(數據屬性中定義的變量)爲真,則對應div增長active類,不然不增長,以下:
<div class="box" v-bind:class='{active:isActive}'></div>
v-on:監聽js中的全部事件,如click,mouseover,mouseout等,以下:
<button v-on:click="clickHandler">切換顏色</button>
v-bind的簡便寫法是":",如:<div class="box" :class='{active:isActive}'></div>
v-on的簡便寫法是"@",如:<button @click="clickHandler">切換顏色</button>
(4)列表渲染v-for(不只能夠遍歷數組,還能夠遍歷對象),以下:
![](http://static.javashuo.com/static/loading.gif)
總結:遍歷數組時,一個參數是值,兩個參數是(值,索引);遍歷對象時,一個參數是值,兩個參數是(值,鍵)。
注意:必定要綁定一個標識(有id就綁定id,沒有id綁定index),則值改變會直接經過key查找,而不用再去遍歷查找,提高效率。
三、Vue應用示例
一、實現輪播圖,代碼以下:
![](http://static.javashuo.com/static/loading.gif)
二、Vue中使用ajax(created是組件建立完成時執行),代碼以下:
![](http://static.javashuo.com/static/loading.gif)
頁面運行效果以下圖:
依次點擊每一項,控制檯效果以下圖:
三、實現音樂播放器,代碼以下:
![](http://static.javashuo.com/static/loading.gif)
四、Vue基礎知識
一、計算屬性(主要產生緩存的數據屬性,防止DOM性能消耗)
模板內的表達式很是便利,可是設計它們的初衷是用於簡單運算的。在模板中放入太多的邏輯會讓模板太重且難以維護。例如:
<div id="example"> {{ message.split('').reverse().join('') }} </div>
在這個地方,模板再也不是簡單的聲明式邏輯。你必須看一段時間才能意識到,這裏是想要顯示變量message 的翻轉字符串。當你想要在模板中屢次引用此處的翻轉字符串時,就會更加難以處理。因此,對於任何複雜邏輯,你都應當使用計算屬性。例如:
![](http://static.javashuo.com/static/loading.gif)
二、偵聽器(watch)
雖然計算屬性在大多數狀況下更合適,但有時也須要一個自定義的偵聽器。這就是爲何 Vue 經過 watch 選項提供了一個更通用的方法,來響應數據的變化。當須要在數據變化時執行異步或開銷較大的操做時,這個方式是最有用的。
watch能夠監聽單個屬性,若是想監聽多個屬性,則聲明多個屬性的監聽,以下:
![](http://static.javashuo.com/static/loading.gif)
注意:計算屬性便可以監聽單個屬性,又能夠監聽多個屬性,以下示例:
![](http://static.javashuo.com/static/loading.gif)
三、計算屬性的應用(上例中音樂播放器改成計算屬性實現)
修改audio標籤的src屬性值,以下:
computed:{ currentSong(){ // 既監聽了musicList,又監聽了currentIndex return this.musicList[this.currentIndex].songSrc } }
總結:計算屬性的方法便可以在模板語法中使用,又能夠在指令系統中使用。
四、關於函數中this指向的問題
Vue實例對象中,通常methods和computed中定義的函數中的this是指當前Vue實例對象,而created中的ajax和定時器中定義的函數中的this是指ajax或者定時器對象,這時,ajax和定時器中的函數改成箭頭函數,就能夠改變this的指向,即this指向當前Vue實例對象。
5、補充知識點
一、查看接口,以下圖:
二、json在線格式化工具:
三、本身查閱資料瞭解js中閉包。
es6快速入門
上次分享了es6開發環境的搭建,本次接着分享es6經常使用的特性。
1.變量聲明let和const
咱們都是知道在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 值爲undefined console.log(test) } //此處訪問test 值爲undefined }
因此不用關心bool是否爲true or false。實際上,不管如何test都會被建立聲明。
接下來ES6主角登場:
咱們一般用let和const來聲明,let表示變量、const表示常量。let和const都是塊級做用域。怎麼理解這個塊級做用域?
- 在一個函數內部
- 在一個代碼塊內部
說白了 {}大括號內的代碼塊即爲let 和 const的做用域。
看如下代碼:
function aa() { if(bool) { let test = 'hello man' } else { //test 在此處訪問不到 console.log(test) } }
let的做用域是在它所在當前代碼塊,但不會被提高到當前函數的最頂部。
再來講說const。
const name = 'lux' name = 'joe' //再次賦值此時會報錯
說一道面試題
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))) } // es6 for (let i = 0; i < 10; i++) { func.push(function() { console.log(i) }) }
達到相同的效果,es6簡潔的解決方案是否是更讓你心動!!!
2.模板字符串
es6模板字符簡直是開發者的福音啊,解決了ES5在字符串功能上的痛點。
第一個用途,基本的字符串格式化。將表達式嵌入字符串中進行拼接。用${}來界定。
//es5 var name = 'lux' console.log('hello' + name) //es6 const name = 'lux' console.log(`hello ${name}`) //hello lux
第二個用途,在ES5時咱們經過反斜槓(\)來作多行字符串或者字符串一行行拼接。ES6反引號(``)直接搞定。
// es5 var msg = "Hi \ man! " // es6 const template = `<div> <span>hello world</span> </div>`
對於字符串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.函數
函數默認參數
在ES5咱們給函數定義參數默認值是怎麼樣?
function action(num) { num = num || 200 //當傳入num時,num爲傳入的值 //當沒傳入參數時,num即有了默認值200 return num }
但細心觀察的同窗們確定會發現,num傳入爲0的時候就是false, 此時num = 200 與咱們的實際要的效果明顯不同
ES6爲參數提供了默認值。在定義函數時便初始化了這個參數,以便在參數沒有被傳遞進去時使用。
function action(num = 200) { console.log(num) } action() //200 action(300) //300
箭頭函數
ES6頗有意思的一部分就是函數的快捷寫法。也就是箭頭函數。
箭頭函數最直觀的三個特色。
- 不須要function關鍵字來建立函數
- 省略return關鍵字
- 繼承當前上下文的 this 關鍵字
//例如: [1,2,3].map( x => x + 1 ) //等同於: [1,2,3].map((function(x){ return x + 1 }).bind(this))
說個小細節。
當你的函數有且僅有一個參數的時候,是能夠省略掉括號的。當你函數返回有且僅有一個表達式的時候能夠省略{};例如:
var people = name => 'hello' + name //參數name就沒有括號
做爲參考
var people = (name, age) => { const fullName = 'h' + name return fullName } //若是缺乏()或者{}就會報錯
4.拓展的對象功能
對象初始化簡寫
ES5咱們對於對象都是以鍵值對的形式書寫,是有可能出現鍵值對重名的。例如:
function people(name, age) { return { name: name, age: age }; }
鍵值對重名,ES6能夠簡寫以下:
function people(name, age) { return { name, age }; }
ES6 一樣改進了爲對象字面量方法賦值的語法。ES5爲對象添加方法:
const people = { name: 'lux', getName: function() { console.log(this.name) } }
ES6經過省略冒號與 function 關鍵字,將這個語法變得更簡潔
const people = { name: 'lux', getName () { console.log(this.name) } }
ES6 對象提供了Object.assign()這個方法來實現淺複製。Object.assign()能夠把任意多個源對象自身可枚舉的屬性拷貝給目標對象,而後返回目標對象。第一參數即爲目標對象。在實際項目中,咱們爲了避免改變源對象。通常會把目標對象傳爲{}
const obj = Object.assign({}, objA, objB)
5.更方便的數據訪問--解構
數組和對象是JS中最經常使用也是最重要表示形式。爲了簡化提取信息,ES6新增瞭解構,這是將一個數據結構分解爲更小的部分的過程
ES5咱們提取對象中的信息形式以下:
const people = { name: 'lux', age: 20 } const name = people.name const age = people.age console.log(name + ' --- ' + age)
是否是以爲很熟悉,沒錯,在ES6以前咱們就是這樣獲取對象信息的,一個一個獲取。如今,解構能讓咱們從對象或者數組裏取出數據存爲變量,例如
//對象 const people = { name: 'lux', age: 20 } const { name, age } = people console.log(`${name} --- ${age}`) //數組 const color = ['red', 'blue'] const [first, second] = color console.log(first) //'red' console.log(second) //'blue'
6.Spread Operator 展開運算符
ES6中另一個好玩的特性就是Spread Operator 也是三個點兒...接下來就展現一下它的用途。
組裝對象或者數組
//數組 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] = number console.log(rest) //2,3,4,5 //對象 const user = { username: 'lux', gender: 'female', age: 19, address: 'peking' } const { username, ...rest } = user console.log(rest) //{"address": "peking", "age": 19, "gender": "female" }
對於 Object 而言,還能夠用於組合成新的 Object 。(ES2017 stage-2 proposal) 固然若是有重複的屬性名,右邊覆蓋左邊
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
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 example
8. Promise
在promise以前代碼過多的回調或者嵌套,可讀性差、耦合度高、擴展性低。經過Promise機制,扁平化的代碼機構,大大提升了代碼可讀性;用同步編程的方式來編寫異步代碼,保存線性的代碼邏輯,極大的下降了代碼耦合性而提升了程序的可擴展性。
說白了就是用同步的方式去寫異步代碼。
發起異步請求
fetch('/api/todos') .then(res => res.json()) .then(data => ({ data })) .catch(err => ({ err }));
今天看到一篇關於面試題的頗有意思。
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);
固然以上promise的知識點,這個只是冰山一角。須要更多地去學習應用。
9.Generators
生成器( generator)是能返回一個迭代器的函數。生成器函數也是一種函數,最直觀的表現就是比普通的function多了個星號*,在其函數體內可使用yield關鍵字,有意思的是函數會在每一個yield後暫停。
這裏生活中有一個比較形象的例子。我們到銀行辦理業務時候都得向大廳的機器取一張排隊號。你拿到你的排隊號,機器並不會自動爲你再出下一張票。也就是說取票機「暫停」住了,直到下一我的再次喚起纔會繼續吐票。
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); // 1 console.log(iterator.next().value); // 2 console.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 來等待異步操做結束。
總結
ES6的特性遠不止於此,但對於咱們平常的開發開說。這已是夠夠的了。還有不少有意思的方法。好比findIndex...等等。包括用set來完成面試題常客數組去重問題。我和個人小夥伴們都驚呆了!