ES6快速入門使用

 https://www.jianshu.com/p/061304806bdajavascript

Babel-webpack的配置

前段項目我想使用ES6的語法我應該怎麼作呢?咱們能夠查看Babel的官方文檔,就簡單用webpack如何配置
因此咱們就能夠先用ES6語言來寫代碼,而後用webpack打包生成ES5的文件,下面只是簡單介紹一下,詳細的能夠查看官方文檔,固然了這只是一種工具,咱們只須要看官網怎麼作的就能夠java

1. Shell npm install --save-dev babel-loader babel-core 2. webpack.config.js module: { rules: [ { test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" } ] } 3. create .babelrc npm install babel-preset-env --save-dev //JSON { "presets": ["env"] } 

var let const

  • var 可聲明前置
var a a = 1 var a = 2 

ES6 新增了let命令,用來聲明變量。它的用法相似於var,但也有區別:node

  • let 不存在變量提高
console.log(bar); // 報錯ReferenceError let bar = 2; a = 1 //報錯 let a 
  • let不容許在相同做用域內,重複聲明同一個變量。
// 報錯 function func() { let a = 10; var a = 1; } // 報錯 function func() { let a = 10; let a = 1; } let a = 3 var a =4 //報錯 let a =5 //報錯 
  • 存在塊級做用域
for(let i =0;i<3;i++){ console.log(i) } console.log(i) //報錯 

塊級做用域的出現,實際上使得得到普遍應用的當即執行函數表達式(IIFE)再也不必要了。webpack

(function(){ var a = 1 })() ==> { let a = 1 } 

ES5 只有全局做用域和函數做用域,沒有塊級做用域,這帶來不少不合理的場景。web

  1. 內層變量可能會覆蓋外層變量。
var tmp = new Date(); function f() { console.log(tmp); if (false) { var tmp = 'hello world'; // var tmp 變量提高 } } f(); // undefined 
  1. 用來計數的循環變量泄露爲全局變量。
var s = 'hello'; for (var i = 0; i < s.length; i++) { console.log(s[i]); // i泄露爲全局變量 } console.log(i); // 5 
  • 暫時性死區(TDZ)
var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; } 

只要塊級做用域內存在let命令,它所聲明的變量就「綁定」(binding)這個區域,再也不受外部的影響。
暫時性死區的本質就是,只要一進入當前做用域,所要使用的變量就已經存在了,可是不可獲取,只有等到聲明變量的那一行代碼出現,才能夠獲取和使用該變量。ajax

  • const

const聲明一個只讀的常量。一旦聲明,常量的值就不能改變。
const一旦聲明變量,就必須當即初始化,不能留到之後賦值。npm

//基本類型 const PI = 3.1415; PI // 3.1415 PI = 3; // TypeError: Assignment to constant variable. //引用類型 const foo = {}; // 爲 foo 添加一個屬性,能夠成功 foo.prop = 123; foo.prop // 123 // 將 foo 指向另外一個對象,就會報錯 foo = {}; // TypeError: "foo" is read-only 

適用let的也適用const編程


解構賦值

ES6 容許按照必定模式,從數組和對象中提取值,對變量進行賦值,這被稱爲解構(Destructuring)。數組

  • 數組的解構賦值
let [a,b,c] = [1,2,3] console.log(a,b,c) // 1 2 3 let [a, [b], c] = [1, [2], 3] a // 1 b // 2 c // 3 let [x, , y] = [1, 2, 3] // x=1 y=3 let [head, ...tail] = [1, 2, 3, 4]; head // 1 tail // [2, 3, 4] 

若是解構不成功,變量的值就等於undefined。bash

let [foo] = []; let [bar, foo] = [1]; 
// 報錯 let [foo] = 1; 

默認值
解構賦值容許指定默認值。
數組對應值有沒有?若是沒有(沒有指undefined),使用默認值,有就使用對應值

let [foo = true] = []; foo // true let [x, y = 'b'] = ['a']; // x='a', y='b' let [x, y = 'b'] = ['a', undefined]; // x='a', y='b' let [a=2,b=3] = [undefined, null] a //2 b //null 
  • 對象的解構賦值
    實際上說明,對象的解構賦值是下面形式的簡寫
let { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" }; 
let { foo, bar } = { foo: "aaa", bar: "bbb" }; foo // "aaa" bar // "bbb" 

對象的解構與數組有一個重要的不一樣。數組的元素是按次序排列的,變量的取值由它的位置決定;而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值。

let { bar, foo } = { foo: "aaa", bar: "bbb" }; foo // "aaa" bar // "bbb" let { baz } = { foo: "aaa", bar: "bbb" }; baz // undefined 沒有同名的 

對象解構的默認值
默認值生效的條件是,對象的屬性值嚴格等於undefined。

var {x = 3} = {}; x // 3 var {x, y = 5} = {x: 1}; x // 1 y // 5 var {x: y = 3} = {}; y // 3 var {x: y = 3} = {x: 5}; y // 5 var { message: msg = 'Something went wrong' } = {}; msg // "Something went wrong" 
  • 字符串的解構賦值
const [a, b, c, d, e] = 'hello'; a // "h" b // "e" c // "l" d // "l" e // "o" 
相似數組的對象都有一個length屬性,所以還能夠對這個屬性解構賦值。

let {length : len} = 'hello'; len // 5 
  • 數值和布爾值的解構賦值

解構賦值時,若是等號右邊是數值和布爾值,則會先轉爲對象。

let {toString: s} = 123; s === Number.prototype.toString // true let {toString: s} = true; s === Boolean.prototype.toString // true 

解構賦值的規則是,只要等號右邊的值不是對象或數組,就先將其轉爲對象。因爲undefined和null沒法轉爲對象,因此對它們進行解構賦值,都會報錯。

let { prop: x } = undefined; // TypeError let { prop: y } = null; // TypeError 
  • 函數參數的解構賦值
function add([x, y] = [1,1]){ return x + y; } add() // 2 add([2]) // 3 add([1, 2]); // 3 function sum({x,y} = {x:0, y:0},{a=1,b=1}){ return [x+a,y+b] } console.log(sum({x:1,y:2},{a:2})) //[3,3] 
  • 解構賦值的做用
  1. 交換變量的值
let x = 1; let y = 2; [x, y] = [y, x]; // [2,1] 
  1. 函數參數默認值
function ajax(url , type='GET'){ } ajax(url:'http://localhost') 

字符串經常使用

  • 字符串模板
// ES5字符串拼接 $('#result').append( 'There are <b>' + basket.count + '</b> ' + 'items in your basket, ' + '<em>' + basket.onSale + '</em> are on sale!' ); 

模板字符串(template string)是加強版的字符串,用反引號(`)標識。它能夠看成普通字符串使用,也能夠用來定義多行字符串,或者在字符串中嵌入變量。

$('#result').append(` There are <b>${basket.count}</b> items in your basket, <em>${basket.onSale}</em> are on sale! `); 

模板字符串中嵌入變量,須要將變量名寫在${}之中

function authorize(user, action) { if (!user.hasPrivilege(action)) { throw new Error( // 傳統寫法爲 // 'User ' // + user.name // + ' is not authorized to do ' // + action // + '.' `User ${user.name} is not authorized to do ${action}.`); } } 

數組擴展經常使用

  • 擴展運算符
    擴展運算符(spread)是三個點(...)
var a = [1,2] console.log(...a) // 1,2 var b = [...a,3] b // [1,2,3] function add(x, y) { return x + y; } const numbers = [4, 38]; add(...numbers) // 42 
... 應用替代apply用法
// ES5 的寫法 Math.max.apply(null, [14, 3, 77]) // ES6 的寫法 Math.max(...[14, 3, 77]) // ES5的 寫法 var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; Array.prototype.push.apply(arr1, arr2); // ES6 的寫法 let arr1 = [0, 1, 2]; let arr2 = [3, 4, 5]; arr1.push(...arr2); 函數參數的擴展 function sort(...arr){ console.log(arr.sort()) } sort(3,1,5) //[1,3,5] 
  • Array.form()
    • Array.from方法用於將兩類對象轉爲真正的數組:相似數組的對象(array-like object)和可遍歷(iterable)的對象(包括 ES6 新增的數據結構 Set 和 Map)。
// NodeList對象 let ps = document.querySelectorAll('p'); Array.from(ps).forEach(function (p) { console.log(p); }); // arguments對象 function foo() { var args = Array.from(arguments); // ... } 
// 類數組對象 let arrayLike = { '0': 'a', '1': 'b', '2': 'c', length: 3 }; // ES5的寫法 var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c'] // ES6的寫法 let arr2 = Array.from(arrayLike); // ['a', 'b', 'c'] 

函數擴展

  • 能夠給參數添加默認值
function log(x, y = 'World') { console.log(x, y); } log('Hello') // Hello World log('Hello', 'China') // Hello China log('Hello', '') // Hello 
//練習,區別? // 寫法一 function m1({x = 0, y = 0} = {}) { return [x, y]; } // 寫法二 function m2({x, y} = { x: 0, y: 0 }) { return [x, y]; } // 函數沒有參數的狀況 m1() // [0, 0] m2() // [0, 0] // x 和 y 都有值的狀況 m1({x: 3, y: 8}) // [3, 8] m2({x: 3, y: 8}) // [3, 8] // x 有值,y 無值的狀況 m1({x: 3}) // [3, 0] m2({x: 3}) // [3, undefined] // x 和 y 都無值的狀況 m1({}) // [0, 0]; m2({}) // [undefined, undefined] m1({z: 3}) // [0, 0] m2({z: 3}) // [undefined, undefined] //總結 ex1: 調用函數須要你傳遞一個對象,若是你沒傳對象就用默認值對象{},默認值對象裏面都是 undefined, 因此屬性使用初始值 ex2:參數須要是一個對象,若是沒傳對象,就用默認值對象{ x: 0, y: 0 }若是傳了對象,就使用你傳遞的對象 
  • 箭頭函數
    • ES6 容許使用「箭頭」(=>)定義函數。
var f = v => v; //等價於 var f = function(v) { return v; }; var f = () => 5; // 等同於 var f = function () { return 5 }; var sum = (num1, num2) => num1 + num2; // 等同於 var sum = function(num1, num2) { return num1 + num2; }; 

若是箭頭函數的代碼塊部分多於一條語句,就要使用大括號將它們括起來,而且使用return語句返回。

var sum = (num1, num2) => { return num1 + num2; } 
  • 箭頭函數的this

函數體內的this對象,就是定義時所在的對象,而不是使用時所在的對象。this對象的指向是可變的,可是在箭頭函數中,它是固定的。

function foo() { setTimeout(() => { console.log('id:', this.id); }, 100); } var id = 21; foo.call({ id: 42 }); // id: 42 

setTimeout的參數是一個箭頭函數,這個箭頭函數的定義生效是在foo函數生成時,而它的真正執行要等到 100 毫秒後。若是是普通函數,執行時this應該指向全局對象window,這時應該輸出21。可是,箭頭函數致使this老是指向函數定義生效時所在的對象(本例是{id: 42}),因此輸出的是42

對象擴展

  • 屬性的簡潔表示法
    ES6 容許直接寫入變量和函數,做爲對象的屬性和方法。這樣的書寫更加簡潔。
const foo = 'bar'; const baz = {foo}; baz // {foo: "bar"} // 等同於 const baz = {foo: foo}; 
function f(x, y) { return {x, y}; } // 等同於 function f(x, y) { return {x: x, y: y}; } f(1, 2) // Object {x: 1, y: 2} 
//方法簡寫 const o = { method() { return "Hello!"; } }; // 等同於 const o = { method: function() { return "Hello!"; } }; 

Module的語法 模塊化

模塊功能主要由兩個命令構成:export和importexport命令用於規定模塊的對外接口,import命令用於輸入其餘模塊提供的功能。

一個模塊就是一個獨立的文件。該文件內部的全部變量,外部沒法獲取。若是你但願外部可以讀取模塊內部的某個變量,就必須使用export關鍵字輸出該變量。下面是一個 JS 文件,裏面使用export命令輸出變量。

// profile.js export var firstName = 'Michael'; export var lastName = 'Jackson'; export var year = 1958; // profile.js var firstName = 'Michael'; var lastName = 'Jackson'; var year = 1958; export {firstName, lastName, year}; //usage.js import {firstName, lastName, year} from './profile'; 

export命令除了輸出變量,還能夠輸出函數或類(class)。

export function multiply(x, y) { return x * y; }; 
  • export default 命令
    使用import命令的時候,用戶須要知道所要加載的變量名或函數名,不然沒法加載,爲了給用戶提供方便,讓他們不用閱讀文檔就能加載模塊,就要用到export default命令,爲模塊指定默認輸出。
// export-default.js export default function () { console.log('foo'); } 

其餘模塊加載該模塊時,import命令能夠爲該匿名函數指定任意名字。

// import-default.js import customName from './export-default'; customName(); // 'foo' 

Class和繼承

ES6 的class能夠看做只是一個語法糖,它的絕大部分功能,ES5 均可以
作到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。上面的代碼用 ES6 的class改寫,就是下面這樣。

//定義類 class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } //等價於 function Point(x, y) { this.x = x; this.y = y; } Point.prototype.toString = function () { return '(' + this.x + ', ' + this.y + ')'; }; var p = new Point(1, 2); 

ES6 的類,徹底能夠看做構造函數的另外一種寫法。

class Point { // ... } typeof Point // "function" Point === Point.prototype.constructor // true 

構造函數的prototype屬性,在 ES6 的「類」上面繼續存在。事實上,類的全部方法都定義在類的prototype屬性上面。

class Point { constructor() { // ... } toString() { // ... } toValue() { // ... } } // 等同於 Point.prototype = { constructor() {}, toString() {}, toValue() {}, }; 

constructor方法是類的默認方法,經過new命令生成對象實例時,自動調用該方法。一個類必須有constructor方法,若是沒有顯式定義,一個空的constructor方法會被默認添加。

class Point { } // 等同於 class Point { constructor() {} } 
  • Class靜態方法
    類至關於實例的原型,全部在類中定義的方法,都會被實例繼承。若是在一個方法前,加上static關鍵字,就表示該方法不會被實例繼承,而是直接經過類來調用,這就稱爲「靜態方法」。
class Foo { //類 static classMethod() { return 'hello'; } } Foo.classMethod() // 'hello' var foo = new Foo(); foo.classMethod() // TypeError: foo.classMethod is not a function 

上面代碼中,Foo類的classMethod方法前有static關鍵字,代表該方法是一個靜態方法,能夠直接在Foo類上調用(Foo.classMethod()),而不是在Foo類的實例上調用。若是在實例上調用靜態方法,會拋出一個錯誤,表示不存在該方法。

  • 繼承
    Class 能夠經過extends關鍵字實現繼承,這比 ES5 的經過修改原型鏈實現繼承,要清晰和方便不少。
class Point { } class ColorPoint extends Point { } 

super 關鍵字

super這個關鍵字,既能夠看成函數使用,也能夠看成對象使用。在這兩種狀況下,它的用法徹底不一樣。

class Person { constructor(name, age) { this.name = name; this.age = age; } sayHello() { console.log( `hello, ${this.name}, i am ${this.age} years old`); } } class Student extends Person { constructor(name, age, score) { super(name, age); this.score = score; } sayScore() { console.log( `hello, ${this.name}, i am ${this.age} years old, i get ${this.score}`); } } 
相關文章
相關標籤/搜索