ES6學習筆記
1、ES6
1.1、什麼是ES6
程式語言JavaScript是ECMAScript的實現和擴充套件 。ECMAScript是由ECMA(一個類似W3C的標準組織)參與進行標準化的語法規範。ECMAScript定義了:
語言語法 – 語法解析規則、關鍵字、語句、宣告、運算子等。
型別 – 布林型、數字、字串、物件等。
內建物件和函式的標準庫 – JSON、Math、陣列方法、物件自省方法等。
ECMAScript標準不定義HTML或CSS的相關功能,也不定義類似DOM(文件物件模型)的Web API,這些都在獨立的標準中進行定義。ECMAScript涵蓋了各種環境中JS的使用場景,無論是瀏覽器環境還是類似
ECMAScript標準的歷史版本分別是1、2、3、5。
那麼為什麼沒有第4版?其實,在過去確實曾計劃釋出提出巨量新特性的第4版,但最終卻因想法太過激進而慘遭廢除(這一版標準中曾經有一個極其複雜的支援泛型和型別推斷的內建靜態型別系統)。
ES4飽受爭議,當標準委員會最終停止開發ES4時,其成員同意釋出一個相對謙和的ES5版本,隨後繼續制定一些更具實質性的新特性。這一明確的協商協議最終命名為“Harmony”,因此,ES5規範中包含這樣兩句話
ECMAScript是一門充滿活力的語言,並在不斷進化中。
未來版本的規範中將持續進行重要的技術改進
2009年釋出的改進版本ES5,引入了
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