var的缺點:(1)var能夠屢次聲明同一個變量; (2)var會形成變量提高 javascript
let以及const都是塊級做用域。咱們經常使用let來聲明一個值會被改變的變量,而使用const來聲明一個值不會被改變的變量,也能夠稱之爲常量。html
常見題:java
如何將結果輸出爲0, 1, 2react
es5處理方法 -- 用函數製造塊級做用域es6
es6處理方法 -- 更加簡單明瞭sql
一、對象的解構賦值數組
const props = { className: 'tiger-button', loading: false, clicked: true, disabled: 'disabled' }
當咱們想要取得其中的2個值:loading與clicked時:瀏覽器
// es5 var loading = props.loading; var clicked = props.clicked; // es6 let { loading, clicked } = props; // 給一個默認值,當props對象中找不到loading時,loading就等於該默認值 let { loading = false, clicked } = props;
// es6 let arr = [1, 2, 3]; let [a, b, c] = arr; // es5 var arr = [1, 2, 3]; var a = arr[0]; var b = arr[1]; var c = arr[2];
數組以序列號一一對應,這是一個有序的對應關係。
而對象根據屬性名一一對應,這是一個無序的對應關係,屬性名一致便可。根據這個特性,使用解析結構從對象中獲取屬性值更加具備可用性。
ES6解構賦值
// es5 var fn = function(a, b) { return a + b; } // es6 箭頭函數寫法,當函數直接被return時,能夠省略函數體的括號 const fn = (a, b) => a + b; // es5 var foo = function() { var a = 20; var b = 30; return a + b; } // es6 const foo = () => { const a = 20; const b = 30; return a + b; }
二、形參默認值(default)服務器
function sum(x,y){ x=x||10; y=y||20; return x+y; }
ES6的默認值寫法:數據結構
function sum(x = 10, y = 20) { return x + y; } console.log(add());
注意:一、箭頭函數是匿名函數,不能做爲構造函數,不能使用new
let FunConstructor = () => { console.log('lll'); } let fc = new FunConstructor();
var obj = { a: 10, b: () => { console.log(this.a); // undefined console.log(this); // Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} }, c: function() { console.log(this.a); // 10 console.log(this); // {a: 10, b: ƒ, c: ƒ} } } obj.b(); obj.c();
var obj = { a: 10, b: function(){ console.log(this.a); //10 }, c: function() { return ()=>{ console.log(this.a); //10 } } } obj.b(); obj.c()();
function A(a){ console.log(arguments); } A(1,2,3,4,5,8); // [1, 2, 3, 4, 5, 8, callee: ƒ, Symbol(Symbol.iterator): ƒ] let B = (b)=>{ console.log(arguments); } B(2,92,32,32); // Uncaught ReferenceError: arguments is not defined let C = (...c) => { console.log(c); } C(3,82,32,11323); // [3, 82, 32, 11323]
從新複習下舊知識:基本數據類型有6種:Undefined、Null、布爾值(Boolean)、字符串(String)、數值(Number)、對象(Object)。
一、Set (相似數組)
主要用來去除重複的數據,Set 自己是一個構造函數,用來生成 Set 數據結構。
let set = new Set(["name1","zhang","wang","name1","zhang"]);
console.log(set); //"name1","zhang","wang"
console.log(set); //3
四個方法:add(),delete(),has(),clear()
二、Map(映射,相似對象)
const map1 = new Map() const objkey = {p1: 'v1'} map1.set(objkey, 'hello') console.log(map1.get(objkey))
結果:
hello
(2)Map能夠接受數組做爲參數,數組成員仍是一個數組,其中有兩個元素,一個表示鍵一個表示值。
const map2 = new Map([ ['name', 'Aissen'], ['age', 12] ]) console.log(map2.get('name')) console.log(map2.get('age'))
結果:
Aissen 12
若是 Map 的鍵是一個簡單類型的值(數字、字符串、布爾值),則只要兩個值嚴格相等,Map 將其視爲一個鍵,包括0和-0,布爾值true和字符串true則是兩個不一樣的鍵。另外,undefined和null也是兩個不一樣的鍵。雖然NaN不嚴格相等於自身,但 Map 將其視爲同一個鍵。
三、symbol(惟一的屬性名)
經常使用於對象的屬性名,不會出現屬性名衝突的現象。
Symbol
函數前不能使用new
命令,不然會報錯。這是由於生成的Symbol是一個原始類型的值,不是對象
Symbol
函數能夠接受一個字符串做爲參數,表示對Symbol實例的描述,主要是爲了在控制檯顯示,或者轉爲字符串時,比較容易區分。
// 沒有參數的狀況 var s1 = Symbol(); var s2 = Symbol(); s1 === s2 // false // 有參數的狀況 var s1 = Symbol("foo"); var s2 = Symbol("foo"); s1 === s2 // false
Symbol值不能與其餘類型的值進行運算
一、class, extends, super
這三個特性涉及了ES5中最使人頭疼的的幾個部分:原型、構造函數,繼承
class Animal { constructor(){ this.type = 'animal' } says(say){ console.log(this.type + ' says ' + say) } } let animal = new Animal() animal.says('hello') //animal says hello class Cat extends Animal { constructor(){ super() this.type = 'cat' } } let cat = new Cat() cat.says('hello') //cat says hello
上面代碼首先用class
定義了一個「類」,能夠看到裏面有一個constructor
方法,這就是構造方法,而this
關鍵字則表明實例對象。
簡單地說,constructor
內定義的方法和屬性是實例對象本身的,而constructor
外定義的方法和屬性則是全部實例對象能夠共享的。
Class之間能夠經過extends
關鍵字實現繼承,這比ES5的經過修改原型鏈實現繼承,要清晰和方便不少。上面定義了一個Cat類,該類經過extends
關鍵字,繼承了Animal類的全部屬性和方法。
super
關鍵字,它指代父類的實例(即父類的this對象)。子類必須在constructor
方法中調用super
方法,不然新建實例時會報錯。這是由於子類沒有本身的this
對象,而是繼承父類的this
對象,而後對其進行加工。若是不調用super
方法,子類就得不到this
對象。
ES6的繼承機制,實質是先創造父類的實例對象this(因此必須先調用super方法),而後再用子類的構造函數修改this。
P.S 若是你寫react的話,就會發現以上三個東西在最新版React中出現得不少。建立的每一個component都是一個繼承React.Component
的類。
一、模板字符串(template string)
你們能夠先看下面一段代碼:
$("#result").append( "There are <b>" + basket.count + "</b> " + "items in your basket, " + "<em>" + basket.onSale + "</em> are on sale!" );
咱們要用一堆的'+'號來鏈接文本與變量,而使用ES6的新特性模板字符串``後,咱們能夠直接這麼來寫:
$("#result").append(` There are <b>${basket.count}</b> items in your basket, <em>${basket.onSale}</em> are on sale! `);
用反引號(\
)來標識起始,用
${} 來引用變量,並且全部的空格和縮進都會被保留在輸出之中
二、數組擴展(Array.from和Array.of)
(1)Array.from是將僞數組對象或可迭代對象轉爲數組實例
let m = new Map([[1, 2], [2, 4], [4, 8]]); Array.from(m); // [[1, 2], [2, 4], [4, 8]]
function f() { return Array.from(arguments); } f(1, 2, 3); // [1, 2, 3]
Array.from([1, 2, 3], x => x + x); // [2, 4, 6] // Generate a sequence of numbers // Since the array is initialized with `undefined` on each position, // the value of `v` below will be `undefined` Array.from({length: 5}, (v, i) => i); // [0, 1, 2, 3, 4]
//數組去重合並
function combine(){ let arr = [].concat.apply([], arguments); //concat() 方法用於鏈接兩個或多個數組。該方法不會改變現有的數組,僅僅返回被鏈接數組的一個副本。
return Array.from(new Set(arr));
} var m = [1, 2, 2], n = [2,3,3]; console.log(combine(m,n)); // [1, 2, 3]
(2)Array.of是將零散的東西集合成一個數組,
Array.of(element0[, element1[, ...[, elementN]]])
Array.of(7); // [7] Array.of(1, 2, 3); // [1, 2, 3] Array(7); // [ , , , , , , ] Array(1, 2, 3); // [1, 2, 3]
兼容舊環境:若是原生不支持的話,在其餘代碼以前執行如下代碼會建立 Array.of()
。
if (!Array.of) { Array.of = function() { return Array.prototype.slice.call(arguments); }; }
三、對象的擴展
(1)key和value相同時,寫一個就夠了。
(2)Object.assign(),將多個對象合爲一個對象
let obj1={name:"July"};
let obj2={age:18};
console.log(Object.assign(obj1,obj2)) //{name:"July",age:18}
四、延展操做符(三點式)
const a = {a: 1, b: 2} const b = {b: 3, c: 4} console.log({...a, ...b, c: 5}) // {a: 1, b: 3, c: 5} // 至關於 Object.assign(a, b, {c: 5})
這兩個傢伙對應的就是es6本身的module
功能。
咱們以前寫的Javascript一直都沒有模塊化的體系,沒法將一個龐大的js工程拆分紅一個個功能相對獨立但相互依賴的小工程,再用一種簡單的方法把這些小工程鏈接在一塊兒。
這有可能致使兩個問題:
(1)一方面js代碼變得很臃腫,難以維護
(2)另外一方面咱們經常得很注意每一個script標籤在html中的位置,由於它們一般有依賴關係,順序錯了可能就會出bug
在es6以前爲解決上面提到的問題,咱們得利用第三方提供的一些方案,主要有兩種CommonJS(服務器端)和AMD(瀏覽器端,如require.js)。
而如今咱們有了es6的module功能,它實現很是簡單,能夠成爲服務器和瀏覽器通用的模塊解決方案。
ES6模塊的設計思想,是儘可能的靜態化,使得編譯時就能肯定模塊的依賴關係,以及輸入和輸出的變量。CommonJS和AMD模塊,都只能在運行時肯定這些東西。
上面的設計思想看不懂也不要緊,咱先學會怎麼用,等之後用多了、熟練了再去研究它背後的設計思想也不遲!
首先咱們回顧下require.js的寫法。假設咱們有兩個js文件: index.js
和content.js
,如今咱們想要在index.js
中使用content.js
返回的結果,咱們要怎麼作呢?
首先定義:
//content.js
define('content.js', function(){
return 'A cat'; })
而後require:
//index.js
require(['./content.js'], function(animal){
console.log(animal); //A cat
})
那CommonJS是怎麼寫的呢?
//index.js
var animal = require('./content.js')
//content.js
module.exports = 'A cat'
//index.js import animal from './content' //content.js export default 'A cat'
以上我把三者都列出來了,媽媽不再用擔憂我寫混淆了...
//content.js
export default 'A cat' export function say(){ return 'Hello!' } export const type = 'dog'
上面能夠看出,export命令除了輸出變量,還能夠輸出函數,甚至是類(react的模塊基本都是輸出類)
//index.js
import { say, type } from './content' let says = say() console.log(`The ${type} says ${says}`) //The dog says Hello
這裏輸入的時候要注意:大括號裏面的變量名,必須與被導入模塊(content.js)對外接口的名稱相同。
若是還但願輸入content.js中輸出的默認值(default),能夠寫在大括號外面。
//index.js
import animal, { say, type } from './content' let says = say() console.log(`The ${type} says ${says} to ${animal}`) //The dog says Hello to A cat
此時咱們不喜歡type這個變量名,由於它有可能重名,因此咱們須要修改一下它的變量名。在es6中能夠用 as
實現一鍵換名。(有點相似sql語句,哈哈)
//index.js
import animal, { say, type as animalType } from './content' let says = say() console.log(`The ${animalType} says ${says} to ${animal}`) //The dog says Hello to A cat
除了指定加載某個輸出值,還可使用總體加載,即用星號(*
)指定一個對象,全部輸出值都加載在這個對象上面。一般 星號*
結合 as
一塊兒使用比較合適。
//index.js
import animal, * as content from './content' let says = content.say() console.log(`The ${content.type} says ${says} to ${animal}`) //The dog says Hello to A cat
想更全面瞭解ES6夥伴們能夠去看阮一峯所著的電子書ECMAScript 6入門