ES6學習筆記
1、ES6
1.1、什麼是ES6
編程語言JavaScript是ECMAScript的實現和擴展 。ECMAScript是由ECMA(一個類似W3C的標準組織)參與進行標準化的語法規範。ECMAScript定義了:
語言語法 – 語法解析規則、關鍵字、語句、聲明、運算符等。
類型 – 布爾型、數字、字符串、對象等。
內建對象和函數的標準庫 – JSON、Math、數組方法、對象自省方法等。
ECMAScript標準不定義HTML或CSS的相關功能,也不定義類似DOM(文檔對象模型)的Web API,這些都在獨立的標準中進行定義。ECMAScript涵蓋了各種環境中JS的使用場景,無論是瀏覽器環境還是類似node.js的非瀏覽器環境。
ECMAScript標準的歷史版本分別是1、2、3、5。
那麼為什麼沒有第4版?其實,在過去確實曾計劃發佈提出巨量新特性的第4版,但最終卻因想法太過激進而慘遭廢除(這一版標準中曾經有一個極其複雜的支持泛型和類型推斷的內建靜態類型系統)。
ES4飽受爭議,當標準委員會最終停止開發ES4時,其成員同意發佈一個相對謙和的ES5版本,隨後繼續制定一些更具實質性的新特性。這一明確的協商協議最終命名為「Harmony」,因此,ES5規範中包含這樣兩句話
ECMAScript是一門充滿活力的語言,並在不斷進化中。
未來版本的規範中將持續進行重要的技術改進
2009年發佈的改進版本ES5,引入了Object.create()、Object.defineProperty()、getters和setters、嚴格模式以及JSON對象。
ECMAScript 6.0(以下簡稱ES6)是JavaScript語言的下一代標準,2015年6月正式發佈。它的目標,是使得JavaScript語言可以用來編寫複雜的大型應用程序,成為企業級開發語言。
1.2、語法新特性
1.2.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 值為undefined
console.log(test)
}
//此處訪問test 值為undefined
}
- 所以不用關心bool是否為true or false。實際上,無論如何test都會被創建聲明。
- 我們通常用let和const來聲明,let表示變量、const表示常量。let和const都是塊級作用域。怎麼理解這個塊級作用域?在一個函數內部 ,在一個代碼塊內部。看以下代碼
function aa() {
if(bool) {
let test = 'hello man'
} else {
//test 在此處訪問不到
console.log(test)
}
}
- const 用於聲明常量,看以下代碼
const name = 'lux'
name = 'joe' //再次賦值此時會報錯
Assignment to constant variable:對常量變量的賦值
1.2.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>`
1.2.3、函數默認參數
- ES6為參數提供了默認值。在定義函數時便初始化了這個參數,以便在參數沒有被傳遞進去時使用。
- 看例子代碼
function action(num = 200) {
console.log(num)
}
action() //200
action(300) //300
1.2.4、箭頭函數
ES6很有意思的一部分就是函數的快捷寫法。也就是箭頭函數。
箭頭函數最直觀的三個特點。
- 不需要function關鍵字來創建函數
- 省略return關鍵字
- 繼承當前上下文的 this 關鍵字
1、基本函數
function funcName(params) {
return params + 2;
}
funcName(2);
2、使用箭頭函數
var funcName = (params) => params + 2
funcName(2)
3、箭頭函數基本語法
(parameters) => { statements }
- 如果沒有參數,那麼可以進一步簡化:
() => { statements }
- 如果只有一個參數,可以省略括號:
parameters => { statements }
- 如果返回值僅僅只有一個表達式(expression), 還可以省略大括號:
parameters => expression
// 等價於:
function (parameters){
return expression;
}
例如:
var double = num => num * 2
double(2);
double(3);
4、沒有局部this的綁定,和一般的函數不同,箭頭函數不會綁定this。 或則說箭頭函數不會改變this本來的綁定。
4.1、我們用一個例子來說明:
function Count() {
this.num = 0;
}
var a = new Count();
4.2、因為使用了關鍵字new構造,Count()函數中的this綁定到一個新的對象,並且賦值給a。通過console.log打印a.num,會輸出0。
console.log(a.num);
4.3、我們來看一下輸出結果:如果我們想每過一秒將a.num的值加1,該如何實現呢?可以使用setInterval()函數。
function Count() {
this.num = 0;
this.timer = setInterval(function add() {
this.num++;
console.log(this.num);
}, 1000);
}
var b = new Count();
4.4、你會發現,每隔一秒都會有一個NaN打印出來,而不是累加的數字。到底哪裡錯了呢? 實際上setInterval裏面的this綁定到全局對象的。我們可以通過將this打印出來驗證這一點:
function Count() {
this.num = 100;
setTimeout(function add(){
this.num++;
console.log(this);
},1000)
}
var a = new Count();
console.log(a.num)
- 回到之前的函數,之所以打印NaN,是因為this.num綁定到window對象的num,而window.num未定義。
4.5、那麼,我們如何解決這個問題呢?使用箭頭函數!使用箭頭函數就不會導致this被綁定到全局對象。
function Count(){
this.num = 100;
setInterval(()=>{
this.num++
console.log(this.num);
},1000)
}
var a = new Count();
console.log(a.num)
- 通過Count構造函數綁定的this將會被保留。在setInterval函數中,this依然指向我們新創建的b對象。
4.6、為了驗證剛剛的說法,我們可以將 Count函數中的this綁定到that, 然後在setInterval中判斷this和that是否相同。
function Counter() {
var that = this;
this.timer = setInterval(() => {
console.log(this === that);
}, 1000);
}
var b = new Counter();
- 總結正如我們期望的,打印值每次都是true。最後,結束刷屏的打印:
5、箭頭函數寫代碼擁有更加簡潔的語法;不會綁定this。
1.2.5、對象初始化簡寫
- ES5我們對於對象都是以鍵值對的形式書寫,是有可能出現鍵值對重名的。例如
function people(name, age) {
return {
name: name,
age: age
};
}
- 以上代碼可以簡寫為
function people(name, age) {
return {
name,
age
};
}
1.2.6、解構
- 數組和對象是JS中最常用也是最重要表示形式。為了簡化提取信息,ES6新增了解構,這是將一個數據結構分解為更小的部分的過程
- ES5我們提取對象中的信息形式如下
const people = {
name: 'lux',
age: 20
}
const name = people.name
const age = people.age
console.log(name + ' --- ' + age)
- 是不是覺得很熟悉,沒錯,在ES6之前我們就是這樣獲取對象信息的,一個一個獲取。現在,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'
1.2.7、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"
1.2.8、import 和 export
- import導入模塊、export導出模塊
- 創建文件lib.js
let fn0=function(){
console.log('fn0...');
}
export {fn0}
- 創建文件demo9.js
import {fn0} from './lib'
fn0();
- 注意:node(v8.x)本身並不支持import關鍵字,所以我們需要使用babel的命令行工具來執行
babel-node demo9
-
使用export default 導出一個對象
Exports.obj={}
export default {
a:20,
say(){
console.log(this.a);
}
};
-
導入的名字可以自定義
Let obj = require(「./vue」);
import v from './vue'
v.say();
1.2.9、Array.some()
- some()方法測試數組中的某個元素是否通過了由提供的函數實現的測試。
- 語法
array.some(callback[, thisObject]);
-
callback – 測試每個元素的函數。
-
thisObject – 執行回調時用作此對象的對象。
-
如果某個元素通過了測試,則返回true,否則返回false。
- 案例
function isBigEnough(element, index, array) {
return (element >= 10);
}
var retval = [2, 5, 8, 1, 4].some(isBigEnough);
console.log("Returned value is : " + retval );
var retval = [12, 5, 8, 1, 4].some(isBigEnough);
console.log("Returned value is : " + retval );
1.2.10、Array.includes()
- Array.includes()判斷是否包含某一元素,它直接返回true或者false表示是否包含某一元素,對NaN一樣有效
- 語法
str.includes(searchString[, position])
-
searchString – 要搜索的子字符串。
-
Position – 此字符串中開始搜索searchString的位置; 默認為0。
-
如果字符串包含子字符串,則為true ; 否則,假。
- 案例
let arr1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', NaN]
arr1.includes('c') // true
arr1.includes('z') // false
arr1.includes(NaN) // true
//includes()函數的第二個參數表示判斷的起始位置
arr1.includes('d', 1) // true
arr1.includes('d', 3) // true
arr1.includes('d', 4) // false
//第二個參數也可以是負數,表示從右數過來第幾個,但是不改變判斷搜索的方向,搜索方向還是從左到右
arr1.includes('k', -1) // false
arr1.includes('k', -2) // true
arr1.includes('i', -3) // false