es6出來很久了一直都沒學,東西挺多的,找了一些博客整理一些經常使用的知識點,按照本身理解敲了一遍代碼,想了解所有的那無疑就是阮一峯大大的博客啦。
參考博客:
ECMAScript 6 入門
實例感覺-es6的經常使用語法和優越性
ES6經常使用知識點概述
JS幾種數組遍歷方式以及性能分析對比html
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]; // 報錯,不可從新賦值地址
複製代碼
用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參數用於收集函數的多餘參數,而且存入一個真正的數組中,這樣就能夠沒必要使用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();
複製代碼
在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
複製代碼
這些都是對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之類的包管理器,將你們的模塊統一管理,使用指令便可下載使用。
是經過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在加載模塊時,會將代碼自動放入一個當即執行函數中造成本身的做用域,這樣全局變量就變成了局部變量。
commonjs雖然能夠實現模塊化,可是機制是同步的,適合後端,對於瀏覽器端,應該使用異步機制,這就產生了AMD,Asynchromous Module Definition,異步加載模塊,是requirejs關於模塊化標準輸出。
// myModule.js
define(['依賴的模塊路徑'], function(依賴模塊名稱){
 ...
 return {
 };
});
// index.js
require(['./myModule'],function(myModule){
})
複製代碼
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'
複製代碼