ES6經常使用知識

es6出來很久了一直都沒學,東西挺多的,找了一些博客整理一些經常使用的知識點,按照本身理解敲了一遍代碼,想了解所有的那無疑就是阮一峯大大的博客啦。
參考博客:
ECMAScript 6 入門
實例感覺-es6的經常使用語法和優越性
ES6經常使用知識點概述
JS幾種數組遍歷方式以及性能分析對比html

let與const

  • 塊級做用域
  • 聲明不提高
  • 不可重複聲明
  • const聲明的爲常量,若是是基本類型,值不可更改,若是是引用類型,引用不可改變,可是值能夠改變
if(true){
    var a=10;
    let b=20;
}
console.log(a); // 10
console.log(b); // 報錯,沒有定義,只能在塊級做用域中使用

function fn(){
    console.log(a1);  // undefined 變量聲明提高,有聲明無初始值
    var a1=10;
    console.log(a2); // 報錯,沒有定義
    let a2=20;
}
fn();

var b=10;
let b=12; //報錯 a已經被聲明

const c1=10;
c1=20; // 報錯,不能更改const常量

const c2=[1,2]; // 數組c2的地址不可更改
c2[1]=3; // 能夠,更改值能夠
console.log(c2); // [1,3]
c2=[1,3]; // 報錯,不可從新賦值地址
複製代碼

編程風格

  • 考慮到var和let語義相同且let沒有全局污染的缺點,應該全面用let替換var
  • let與const均可以時,應該使用const,全部的函數表達式都應該使用const,全部的全局參數都應該儘可能使用const

字符串

字符串模板

用es5寫一些較長的含有變量的字符串時,老是使用+號進行拼接,極其不方便,es6提供了字符串模板的方式填充變量。
字符串模板必須使用在反引號``中java

// es5
var a=10;
var b='<div id="'+a+'"></div>'; // 拼接很麻煩,尤爲是涉及到單雙引號
console.log(b); // <div id="10"></div>

// es6
let c=`<div id="${a}"></div>` // 放到反引號中
console.log(c) // <div id="10"></div>

// 反引號中全部的空格都會保留,可使用trim()去除頭尾的空格
複製代碼

字符串遍歷/數組遍歷/對象遍歷

es6新增了字符串的遍歷接口node

let str='abcdefg';
for(let s of str){
  console.log(s); // a b c d e f g
}
複製代碼

再整理一下數組和對象經常使用的遍歷方法python

// 數組遍歷

// for循環是最經常使用的一種
for(let i=0;i<arr.length;i++){
}

// 將數組長度保存下來,是上面一種的改進版本,幾種遍歷方法中性能最好
for(let i=0,len=arr.length;i<len;i++){
}

// for in,用法上是for循環的變體,但效率是最低的
for(let key in arr){
    console.log(arr[key])    
}

// for of,es6提供的,同時支持一些類數組的遍歷 
for(let value of arr){
    console.log(value)
}

// forEach(),能夠同時操做value和key,可是性能比不上for循環
arr.forEach(function(value,key,arr){
})

// 對象遍歷

// for in ,遍歷對象自身和繼承的可枚舉屬性
for(let key in obj){
    console.log(obj[key])
}

// Object.keys(obj)
// Object.keys返回一個數組,包括對象自身的全部可枚舉屬性的鍵名。
Object.keys(obj).forEach(function(key){
    console.log(obj[key])
})

// Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一個數組,包含對象自身的全部屬性,包括不可枚舉屬性的鍵名。
Object.getOwnPropertyNames(obj).forEach(function(key){
    console.log(obj[key])
})
複製代碼

解構賦值

es6容許按照必定的模式從數組和對象中提取值,而後對變量進行賦值。c++

// 一一對應
let [a,b,c] = [1,2,3]
console.log(`${a}====${b}====${c}`) // 1====2====3

let [s1,arr] = [1,[1,2,3]] 
console.log(s1) // 1
console.log(arr) // [1,2,3]

// 左少右多
let [a,b]=[1,2,3,4] // a=1,b=2
// 左多右少
let [a,b,c,d]=[1,2] // a=1,b=2,c=undefined,d=undefined

// 能夠默認值
let [a,b,c=10]=[1,2] // a=1,b=2,c=10

// 與擴展運算符一塊兒使用
let [a,...arr]=[1,2,3,4]
console.log(a) // 1
console.log(arr) // [2,3,4]

// 對象的解構
let {name, age} = {name:'xx',age: 10} 
console.log(name) // xx
console.log(age) // 10

// 對象的解構賦值與順序沒有關係,而是屬性名相同
// let {name, age} = {name:'xx',age: 10} 與 let {age,name} = {name:'xx',age: 10}結果相同

// let {age,name} 是let {name:name,age:age}的簡寫,賦值的是後面的屬性變量
let { foo: baz , bar } = { foo: "aaa", bar: "bbb" }; 
foo // foo is not defined
baz // 'aaa'
bar // 'bbb 複製代碼

編程風格

  • 當使用多個數組元素時,優先考慮解構賦值
const arr = [1, 2, 3, 4];

// bad
const first = arr[0];
const second = arr[1];

// good
const [first, second] = arr;
複製代碼
  • 當函數參數爲對象時,優先考慮解構賦值
// bad
function getFullName(user) {
  const firstName = user.firstName;
  const lastName = user.lastName;
}

// good
function getFullName(obj) {
  const { firstName, lastName } = obj;
}

// best
function getFullName({ firstName, lastName }) {
}
複製代碼

函數

箭頭函數

// es5
var add=function(x,y){
    rerturn x+y;
}

// es6
const add=(x,y)=>x+y

// 沒有參數
const f=()=>5
//等同於
var f=function(){
    return 6
}

// 只有一個參數
const f=x=>x+5
// 等同於
var f=function(x){
    return x+5
}

// 有多個參數和語句
const f=(x,y)=>{x++;y++;return x+y}
複製代碼

** 注意 ** 箭頭函數內部沒有this, 因此不可看成構造函數使用,由於沒有this,因此在箭頭函數內部使用this的話,會綁定到箭頭函數定義時的做用域。
箭頭函數的該特性特別適合用於回調函數。es6

var handler = {
  id: '123456',

  init: function() {
    document.addEventListener('click',
      event => this.doSomething(event.type), false);
  },

  doSomething: function(type) {
    console.log('Handling ' + type  + ' for ' + this.id);
  }
};
// 這裏的this始終指向handler, 而若是是普通函數的話,則會使用調用該函數的對象,即document,就會出現錯誤。
複製代碼

reset參數

reset參數用於收集函數的多餘參數,而且存入一個真正的數組中,這樣就能夠沒必要使用arguments這個僞數組參數了。npm

function add(...values) {
  let sum = 0;
  for (var val of values) {
    sum += val;
  }
  return sum;
}

add(2, 5, 3) // 10

// 替換arguments
// arguments變量的寫法
function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort();
}

// rest參數的寫法
const sortNumbers = (...numbers) => numbers.sort();
複製代碼

編程風格

  • 單行的,簡單的,不用複用的函數都儘可能使用箭頭函數
  • 須要綁定this的函數也使用箭頭函數
  • 複雜的常常複用的函數仍是須要使用通常函數
  • 使用reset參數代替arguments

class與extends

在es5中使用構造函數和原型的方式來定義類,es6封裝了class來更接近java/c++等語言的編寫習慣.編程

// es5
function Person(x,y){
    this.x=x;
    this.y=y;
}
Person.prototype.say=function(){
    return this.x+this.y
}
var p=new Person('x','y')

// es6將其改寫爲
class Person{
    constructor(x,y){
        this.x=x;
        this.y=y;
    }
    say(){
        return this.x+this.y
    }
}
let p=new Person(x,y) // 默認會調用constructor
p.say()
複製代碼

全部在類中聲明的方法其實都是定義在protoytpe屬性上。
在es5中通常使用組合繼承的方式來實現繼承,寫起來很麻煩,es6採用extends關鍵字來實現繼承,也更貼近java/c++的寫法。後端

class Person{
  constructor(x,y){
    this.x=x;
    this.y=y;
  }
  say(){
    console.log(`${this.x}++++++${this.y}`)
  }
}

let p=new Person('xixi',10);
p.say(); // xixi++++++10

class Girl extends Person{
  constructor(name,age,sex){
    super(name,age) // 調用父類構造函數,必需要寫,後面才能使用this
    this.sex=sex
  }
  play(){
    super.say() // 調用父類方法
    console.log(this.sex)
  }
}

let g=new Girl('xi',10,'girl')
g.play() // xi++++++10 girl
複製代碼

編程風格

  • 應該使用class與extends來代替es5中的構造函數和原型繼承

CommonJS/AMD/ES6 Module

這些都是對js模塊化的規範輸出,所謂js模塊化,我理解的就是一個js文件就是一個模塊,裏面封裝了某些功能,能夠在其餘地方導入使用,像python裏import某個包同樣。
可使用外聯script的形式引入別人的js代碼,如:數組

<script src='file1.js'>
<script src='file2.js'>
<script src='file3.js'>
複製代碼

可是這樣須要注意引用順序,如file2.js裏面須要file1.js裏面的某個函數,必需要放在file1.js後面,同時還存在變量污染的問題。因此就出現了模塊的概念,模塊裏面的變量是私有的,不會影響到別的模塊裏的變量,同時爲了能夠方便的使用其餘人的模塊,而不是須要一個個去輸入網址去找版本下載,也出現了npm之類的包管理器,將你們的模塊統一管理,使用指令便可下載使用。

CommonJS

是經過node.js實現的,在後端使用的模塊化規範。

// add.js
function add(x,y){
    return x+y
}
module.exports=add

// index.js
const add=require('./add.js')
複製代碼

導出模塊的原理,首先nodejs會先準備一個module對象:

// 準備module對象:
var module = {
    id: 'add',
    exports: {}
};
var load = function (module) {
    // 讀取的add.js代碼:
    function add(x,y){
        return x+y
    }
    
    module.exports = add;
    // add.js代碼結束
    return module.exports;
};
var exported = load(module);
// 保存module:
save(module, exported);
複製代碼

Node保存了全部導入的module,當咱們用require()獲取module時,Node找到對應的module,把這個module的exports變量返回,這樣,另外一個模塊就順利拿到了模塊的輸出:

const add=require('./add.js')
複製代碼

關於模塊中變量不會污染,是由於nodejs在加載模塊時,會將代碼自動放入一個當即執行函數中造成本身的做用域,這樣全局變量就變成了局部變量。

AMD

commonjs雖然能夠實現模塊化,可是機制是同步的,適合後端,對於瀏覽器端,應該使用異步機制,這就產生了AMD,Asynchromous Module Definition,異步加載模塊,是requirejs關於模塊化標準輸出。

// myModule.js
define(['依賴的模塊路徑'], function(依賴模塊名稱){
&emsp;...
&emsp;return {
&emsp;};
});

// index.js
require(['./myModule'],function(myModule){
})
複製代碼

es6 module

es6也規範了模塊化的概念,比requirejs更加高效,使用的是export和import

// 能夠導出多種形式
export var a=10

var m=1
export {m} // 必須加{}

var fn=function(){}

export fn=function(){}
export {fn}

// 引入
import {fn} from './xxx.js'
import * from './xxx.js'
複製代碼
相關文章
相關標籤/搜索