ES6(ES2015)已經發布四年了,其實平時開發中用的不少,可是有不少時候基於各類考慮仍是不能放手大膽的使用,實際上是由於對一些新特性尚未完全掌握,今天總結一下最常使用的幾個特性。前端
衆所周知,在JavaScript中,變量默認是全局性的,只存在函數級做用域,聲明函數曾經是創造做用域的惟一方法。這點和其餘編程語言存在差別,其餘語言大多數都存在塊級做用域。因此在ES6中,新提出的let關鍵字使這個缺陷獲得了修復。express
if (true) {
let a = 'name';
}
console.1og (a);
// ReferenceError:a is not defined
複製代碼
同時還引入的概念是const,用來定義一個常量,一旦定義之後不能夠修改,不過若是是引用類型的,那麼能夠改變它的屬性。編程
const MYNAME = 'viking';
MYNAME = 'kitty';
// "CONSTANT" is read-only
const MYNAME = ({foo: 'viking'};
MYNAME.foo = 'kitty';
//能夠正常運行
複製代碼
箭頭函數是一種更簡單的函數聲明方式,能夠把它看做是一種語法糖,箭頭函數永遠是匿名的。數組
let add = (a, b) => {
return a + b;
}
//當後面是表達式(expression)的時候,還能夠簡寫成
let add = (a, b) => a + b;
//等同於
let add = function (a, b) {
return a + b;
}
//在回調函數中應用
let numbers = [1, 2, 3];
let doubleNumbers = numbers.map((number) => number * 2);
console.log(doubleNumbers);
//[2,4, 6]看起來很簡便吧
複製代碼
在工做中常常會遇到這樣的問題,就是this在一個對象方法中嵌套函數。瀏覽器
var age = 2;
var kitty= {
age: 1,
grow: function() {
setTimeout (function() {
console.log(++this.age) ;
}, 1000);
}
};
kitty.grow(); // 3
複製代碼
在對象方法的嵌套函數中,this 會指向global對象,這被看做是JavaScript在設計上的一個重大缺陷,通常都會採用一些hack來解決它,以下:bash
let kitty = {
age: 1,
grow: function () {
const self = this;
setTimeout(function () {
console.log(++self.age);
}, 100);
}
}
//或者
let kitty = {
age: 1,
grow: function () {
setTimeout(function () {
console.log(++this.age);
}.bind(this), 100);
}
}
複製代碼
如今有了箭頭函數,能夠很輕鬆地解決這個問題。app
let kitty = {
age: 1,
grow: function () {
setTimeout(() => {
console.log(this.age);
}, 100);
}
}
複製代碼
ES6沒有出現以前,面對默認參數都會讓人感到很痛苦,不得不採用各類hack,好比說: values = values[0]。如今一切都變得輕鬆不少。編程語言
function desc(name = ' Peter', age = 5) {
return name + ' is ' + age + ' years old ';
}
desc();
//Peter is 5 years old
複製代碼
當一個函數的最後一個參數有 「..."這樣的前綴,它就會變成一個參數的數組。模塊化
function test(...args) {
console.log(args);
}
test(1, 2, 3);
// [1, 2, 3]
function test2(name, ...args)(
console.log(args);
}
test2('Peter', 2, 3);
//[2,3]
複製代碼
它和arguments有以下區別:函數
①Rest參數只是沒有指定變量名稱的參數數組,而arguments是全部參數的集合;
②arguments 對象不是一個真正的數組,而Rest參數是一個真正的數組,可使用各類方法,好比sort、map 等。
有了這兩個理由,是時候告別arguments,擁抱可愛的Rest參數了。
剛纔在函數中講到了使用「...」操做符來實現函數參數的數組,其實這個操做符的魔力不只僅如此。它被稱爲展開操做符,容許一個表達式在某處展開,在存在多個參數(用於函數調用)、多個元素(用於數組字面量)或者多個變量(用於解構賦值)的地方就會出現這種狀況。
若是在以前的JavaScript中,想讓函數把一個數組依次做爲參數進行調用,通常會以下這樣作。
function test(x, y, z) { };
var args = [1, 2, 3],
test.apply (null, args);
複製代碼
有了ES6的展開運算符,能夠簡化這個過程。
function test(x, y, z) { };
let args = [0,1, 2]
test(...args) ;
複製代碼
在以前的版本中,若是想建立含有某些元素的新數組,經常會用到splice、concat、push等方法,以下。
var arrl = [1, 2, 3];
var arr2 = [4, 5, 6];
var arr3 = arr1.concat(arr2) ;
console.log(arr3);
// 1.2.3.4.5,6
複製代碼
使用展開運算符之後就簡便了不少,以下:
let arr1 = (1, 2, 3);
let arr2 = [4,5, 6];
let arr3 = [...arr1, ...arr2];
console.log(arr3);
// 1,2,3,4.5,6
複製代碼
數組的展開運算符簡單易用,那麼對象有沒有這個特性?
let mike = {name: 'mike', age: 50};
mlke = {...mike, sex: 'male'};
console.log (mlke);
/*
{
age: 50,
name: "mike" ,
sex: "male"
}
*/
複製代碼
對象的展開運算符其實已經被提上日程,只不過它是ES7的提案之一,它可讓你以更簡潔的形式將一個對象可枚舉的屬性複製到另一個對象上。這一特性能夠藉助的Babel和它的插件來實現。
在ES6以前的時代,字符串的拼接老是一件使人不爽的事情,可是在ES6來臨的時代,這個痛處也要被治癒了。
//以前總會作這些事情
var name = 'viking';
var a = 'My name is ' + name + '|';
//多行字符串
var longStory = 'This is a long story,'
+ 'this is a long story',
+ 'this is a long story.';
// 有了ES6如今能夠這樣作
// 注意這裏不是引號而是這個符號
let name = 'viking';
let a = `My name is ${name} !`;
let longStory = `This is a long story,
this is a long story
this is a long story~`;
//很是方便,對吧
複製代碼
解構語法能夠快速從數組或者對象中提取變量,能夠用一個表達式讀取整個結構。
let foo = ['one', 'two', 'three'];
let [one, two, three] = foo;
console.log(${one}, ${two}, ${three});
//one, two, three
複製代碼
let person = {name: 'viking', age: 20};
let {name, age} = person;
console, log(${name}, ${age});
//viking, 20
複製代碼
解構賦值能夠看做一種語法糖,它受Python語言的啓發,能夠提升效率。
衆所周知,在JavaScript的世界裏是沒有傳統類的概念的,它使用原型鏈的方式來完成繼承,可是聲明的方式看起來老是怪怪的,因此ES6提供了class這個語法糖,讓開發者能夠模仿其餘語言類的聲明方式,看起來更加明確清晰。須要注意的是,class並無帶來新的結構,而只是原來原型鏈方式的一種語法糖。
class Animal {
//構造函數
constructor(name, age) {
this.name = name;
this.age = age;
}
shout() {
return `My name is ${this.name}, age is ${this.age}`;
}
//靜態方法
static foo() {
return 'Here is a static method';
}
}
const cow = new Animal('betty', 2);
cow.shout();
// My name is betty, age is 2
Animal.foo();
//Here is a static method
class Dog extends Animal {
constructor(name, age = 2, color = 'black') {
//在構造函數中能夠直接調用super方法
super(name, age);
this.color = color;
}
shout() {
//在非構造函數中不能直接使用super方法
//可是能夠採用super(). +方法名宇調用父類方法
return super.shout() + `,color is ${this.color}.`;
}
}
const jackTheDog = new Dog('jack');
jackTheDog.shout();
//"My name is jack, age is 2,color is black"
複製代碼
JavaScirpt模塊化代碼是一個古老的話題,從前端開發這個職業誕生到如今一直都在不斷地進化,它的發展也從外一個側面反映了前端項目愈來愈複雜、愈來愈工程化。
在ES6以前,JavaScript並無對模塊作出任何定義,因而先驅者們創造了各類各樣的規範來完成這個任務。伴隨着Require.js的流行,它所推崇的AMD格式也成了開發者的首選。在這以後,Node.js誕生了,隨之而來的是CommonJS格式,再以後browserify的誕生,讓瀏覽器端的開發也能使用這種格式。直到ES6的出現,模塊這個觀念才真正有了語言特性的支持,如今來看看它是如何被定義的。
//hello.js文件
//定義一個命名爲hello的函數
function hello() {
console.log('Hello ES6');
}
//使用export導出這個模塊
export hello;
//main.js
//使用import加載這個模塊
import { hello } from ' ./hello';
hello();
//Hello ES6
複製代碼
上面的代碼就完成了模塊的一個最簡單的例子,使用import和export關鍵字完成模塊的導入和導出。固然也能夠完成一個模塊的多個導出,請看下面的例子。
//hello.js
export const PI = 3.14;
export function hello() {
console.log('Hello ES6');
}
export let person = {name: 'viking');
//main.js
//使用對象解構賦值加載這3個變量
import {PI, hello, person} from './hello';
//也能夠將這個模塊所有導出
import * as util from './hello';
console.log (util.PI);
//3.14
複製代碼
還可使用default關鍵字來實現模塊的默認導出;
//hello.js
export default function () (
console.log('Hello ES6');
}
//main.js
import hello from './hello';
hello();
//Hello ES6
複製代碼
模塊的官方定義對於JavaScript來講是具備劃時代意義的,它讓各類關於JavaScript模塊化標準的爭鬥落下帷幕,開發者不用再爲選擇什麼樣的模塊標準而苦惱,每一個人均可以開心地使用ES6的模塊標準。
以上就是ES6中比較重要且經常使用的一些語言特性啦!
更多精彩內容歡迎關注個人公衆號【天道酬勤Lewis】