1.塊級做用域的引入javascript
在ES6以前,js只有全局做用域和函數做用域,ES6中let關鍵字爲其引入了塊級做用域。html
{ var a = 5; let b = 6; } console.log(a); //5 console.log(b); //b is undefined
let聲明的變量只能在其所在的代碼塊內才能訪問,var聲明的變量因爲是全局變量,所以能夠在代碼塊外訪問java
2.暫時性死區node
var聲明的變量能夠在聲明以前使用,至關於默認爲其聲明其值爲undefined了;es6
可是,let聲明的變量一旦用let聲明,那麼在聲明以前,此變量都是不可用的,術語稱爲「暫時性死區」。ajax
console.log(a); //undefined var a=8; console.log("----------"); console.log(b); //控制檯報錯 let b=9;
因此咱們要養成變量先聲明再使用的好習慣。json
3.const命令數組
const用來定義常量,至關於java中的final關鍵字。promise
而且const聲明常量以後就必須當即初始化!瀏覽器
4.解構賦值
let [a,b,c] = [1,2,3]; let{x1,x2} = {x2:5,x1:6}; const [a,b,c,d,e]= "hello"; function add([i,j]) {}---add([5,6]);
能夠理解爲「模式匹配」。
5.字符串
Unicode表示法
"\u{碼點}" "\u{41}\u{42}\u{43}" //"ABC"
let str = "書劍恩仇錄"; str.codePointAt(0).toString(16); //返回字符的碼點並由十進制轉到16進制---66f8 String.fromCodePoint(0x66f8); //返回碼點對應的字符---書 for (let a of str){ console.log(a); } //for...of循環遍歷字符串中每一個字符挨個輸出字符 str.at(0); //返回指定位置的字符,目前只是提案 str.startsWith('書',0); //從指定位置日後開始檢查,是否以「書」開始,位置參數可省略,默認爲0 str.endsWith('劍',1); //從指定位置向前檢查,是否以「劍」結束 str.includes('恩',1); //同上,再也不囉嗦 str.repeat(2); //字符串重複指定次數「書劍恩仇錄書劍恩仇錄」,小數取整,Infinity和負數報錯 str.padStart(8,'ab'); //指定字符從前開始補直到字符串長度符合要求,"aba書劍恩仇錄" str.padEnd(8,'ab'); //指定字符從後開始補直到字符串長度符合要求,"書劍恩仇錄aba",若長度小於原長度,返回原字符串,上同
6.模板字符串
模板字符串採用反引號(`)標識,而且模板字符串中的空格、換行將在輸出時有所保留。
// 普通字符串 `In JavaScript '\n' is a line-feed.` // 多行字符串 `In JavaScript this is not legal.` console.log(`string text line 1 string text line 2`); // 字符串中嵌入變量 let name = "Bob", time = "today"; `Hello ${name}, how are you ${time}?`
${主體},其中主體能夠是表達式、運算、對象屬性還能夠是函數,如果字符串將直接輸出該字符串。
7.含參函數的調用
function say(something){ console.log("she say"+" '"+something+"'" ); } say`hello`; //she say 'hello'
等同於say('hello')。
8.數值拓展
和字符串對象相似的,ES6也爲數值類對象例如Number、Math添加了新的方法以及屬性(常量),在這裏就很少做記錄。
9.函數function
function show(name="jack",sex="boy"){ console.log(name+" is a "+sex+"!"); } show(); //jack is a boy! show('judy'); //judy is a boy! show('judy','girl'); //judy is a girl!
爲函數的參數添加默認值,執行函數時若是不傳該參數,那麼就用默認值代替。
箭頭函數:
var 變量名/函數名 = (參數,參數)=>{代碼塊}
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的是一個對象{id:id,age:age},那麼箭頭右邊要用括號包起來().
10.數組的擴展
擴展運算符爲三個點(...),將一個數組轉化爲參數序列,一般與函數一塊兒使用,show(...['judy','girl'])。
數組合並:[...arr1,...arr2,...arr3]
字符串轉字符數組:[..."hello"]--------------["h","e","l","l","o"]
將實現Iterator接口的對象轉化爲真正的數組:[...nodelist],這裏的nodelist是一個相似於數組的nodelist對象
Generator 函數:該函數執行後返回一個遍歷器對象,拓展運算符也可將其轉化爲數組。
let a =function*(){ yield 3; yield 4; yield 5; return 6; }; console.log([...a()]); //[3,4,5]
11.數組的方法
Array.from(對象,對新數組各項的改動規則)
這裏的對象只適合①類數組對象②實現Iterator接口的對象;後面的規則可選
e.g:
Array.from([1, 2, 3], (x) => x * x) //這裏將數組每項按必定規則改變生成新數組[1,4,9]
Array.of(數據1,數據2,數據3)
將一組數據轉化爲數組
e.g:
Array.of(1,2,3,4,5) //[1,2,3,4,5]
copyWithin(被覆蓋起始位置,選取的數據起始位置,選取額數據結束位置)
截取數組的一段數據,並覆蓋到指定位置
e.g:
[1,2,3,4,5].copyWithin(0,2,4) //被截取數據位置爲[2,4)---[3,4],替換起始位置是0,因此結果是[3,4,3,4,5]
find(規則)、findIndex(規則)
這裏的規則是一個回調函數,找到了就返回這個數組項/索引,找不到返回undefined/-1
e.g:
[9,8,7,6,5,4,3].find(n=>n<5) //返回4
還能夠添加第二個參數,以下
function f(v){ return v > this.age; } let c =function(v){ return v > this.age; } let person = {name: 'John', age: 20}; let a =[10, 12, 26, 15].find(c, person); //c、f均可以 console.log(a); //26
fill(被填充數據,起始位置,結束位置)
若是起始位置、結束位置不寫,那麼就默認所有填充
e.g:
[2,2,2,2,2,2].fill(8,2,4) //將8覆蓋原[2,4)位置上的數據,[2,2,8,8,2,2]
注意,若是給每項賦值的是一個對象,那麼實際上只是一個指針,若改變一個位置的對象內容,那麼全部項
的對象內容都會改變。
let b = {name:'jack'}; let a =[2,2,2,2,2,2].fill(b,1,4) ; console.log(a); //[ 2, { name: 'jack' }, { name: 'jack' }, { name: 'jack' }, 2, 2 ] a[1].name = "echo"; console.log(a); //[ 2, { name: 'echo' }, { name: 'echo' }, { name: 'echo' }, 2, 2 ]
for...of遍歷數組的鍵、值、以及各項鍵值對信息
for (let index of ['a', 'b'].keys()) { console.log(index); } // 0 // 1 for (let elem of ['a', 'b'].values()) { console.log(elem); } // 'a' // 'b' for (let [index, elem] of ['a', 'b'].entries()) { console.log(index, elem); } // 0 "a" // 1 "b"
備註:有的瀏覽器沒有實現數組的values()方法,好比:Chrome!
12:對象的拓展
對象裏面能夠直接寫入變量和函數
//before: var person = { name:'eco', age:18, say:function(something){ console.log("hello "+something); } }; person.say('world'); //now: var firstname='jack'; var man = { firstname, say(something){ console.log(this.firstname); console.log("hello "+something); } }; man.say('world');
屬性名/方法名:能夠用中括號裏面加上表達式的方式
e.g:
var a = 'age';
person.age=person['age']=person[a]
方法的name屬性返回方法名
person.say.name //"say"
Object.is(值1,值2)用於比較兩個值是否相等,返回布爾值
Object.assign(targetobject,sourceobject1,sourceobject2)
用於對象的合併,將源對象合併到目標對象,如有相同屬性源對象屬性覆蓋目標對象屬性
若是源對象是其餘數據類型,只有字符串會以字符數組形式拷到目標對象,其餘類型不會有效果。
const v1 = 'abc'; const v2 = true; const v3 = 10; const obj = Object.assign({}, v1, v2, v3); console.log(obj); // { "0": "a", "1": "b", "2": "c" }
對象的屬性描述:Object.getOwnPropertyDescriptors(obj)
對象的繼承相關:
Object,setPrototypeOf(obj,proto) //爲obj對象設置一個原型對象,那麼obj繼承了proto對象的全部屬性
Object.getPrototypeOf(obj) //不難看出,這是讀取一個對象的原型對象
super //指向當前對象的原型對象,至關於java中的超類
13.Symbol函數
爲了防止不一樣人員書寫代碼形成變量名/方法名的衝突
let a = Symbol(); let b = Symbol(); //函數能夠添加帶有描述性語言的字符串參數 a === b ; //false
14.Set和Map數據結構
Set:成員不重複的類數組結構
Set屬性:size---返回成員總數
Set操做方法:add(value)---返回Set、delete(value)---返回布爾、has(value)---返回布爾、clear()---無返回值
Set遍歷方法:keys()---返回鍵(索引)的遍歷器、values()---返回值的遍歷器、
entries---返回鍵值對的遍歷器、forEach(callback())---遍歷每一個成員,並經過回調函數基於數據作點什麼
WeakSet:相似於Set,只是它的成員只能是對象,沒有size,不能遍歷
Map:廣義上的鍵值對集合,鍵的範圍不侷限於字符串,對象也能夠看成鍵
Map操做方法:set(key,value)---設置成員、get(key)---讀取指定鍵的值,若無返回undefined
const set = new Set([1, 2, 3, 4, 4]); //[...set]---[1,2,3,4] const map = new Map([ ['name', '張三'], ['title', 'Author'] ]);
15.Proxy代理
var handler = { get: function(target, name) { if (name === 'prototype') { return Object.prototype; } return 'Hello, ' + name; }, apply: function(target, thisBinding, args) { return args[0]; }, construct: function(target, args) { return {value: args[1]}; } }; var fproxy = new Proxy(function(x, y) { return x + y; }, handler); fproxy(1, 2) // 1 new fproxy(1, 2) // {value: 2} fproxy.prototype === Object.prototype // true fproxy.foo === "Hello, foo" // true
咱們能夠看出,上面聲明瞭一個變量/函數fproxy,而且爲其添加了一個攔截器對象handler,
那麼對fproxy進行一些操做行爲的時候,會優先被這個攔截器捕獲,進行特定處理後輸出結果
var fproxy = new Proxy(target,handler); //一個Proxy實例
construct:構造一個新的fproxy時會觸發攔截器的該方法,new fproxy(1,2)===>return {value : args[1]}===>{value : 2}
apply:函數執行時會觸發攔截器的該方法,fproxy(1,2)===>return args[0]===>1
get:讀取屬性值的時候會觸發攔截器的該方法,fproxy.foo===>foo對應該方法的參數name,return 'Hello, '+name;===>"Hello, foo"
set:設置屬性值的時候會觸發攔截器的該方法。
備註:
let obj = Object.create(fproxy);
這裏爲obj設置了原型fproxy,那麼obj繼承了fproxy的全部屬性,obj.foo===>fproxy.foo===>"Hello, foo"
Proxy支持的攔截操做除了上面的4中以外還有9中,有興趣的請點擊 Proxy。
16.Reflect反射
相似於java的反射,在跳過編譯、不加載類的前提下,動態地調用類中的方法。
和Proxy相對應的,Reflect也有13個靜態方法,詳情請點擊 Reflect。
Reflect.get(target,name,receiver)------------讀取target對象(必須是對象)的name屬性值,若無返回undefined,
若name屬性有get聲明,那麼name函數中的this指向receiver對象。
Reflect.set(target,name,value,receiver)----設置target對象(必須是對象)的name屬性值爲value,
若name屬性有set聲明,那麼name函數中的this指向receiver對象。
注意:當Proxy和Reflect同時使用時,爲一個Proxy實例賦值時,觸發set攔截,若set攔截方法體內又有
Reflect.set(target,name,value,receiver),那麼這又會觸發攔截器的defineProperty攔截,前提是反射操做
傳入了receiver參數!!!
Reflect.has(obj,name)---------------------------返回布爾值,表示obj對象中有沒有name屬性。
17.Promise---異步
先來看ajax的異步:
$(function(){ $('#send').click(function(){ $.ajax({ type: "GET", url: "test.json", data: {username:$("#username").val(), content:$("#content").val()}, dataType: "json", success: function(data){ $('#resText').empty(); //清空resText裏面的全部內容 var html = ''; $.each(data, function(commentIndex, comment){ html += '<div class="comment"><h6>' + comment['username'] + ':</h6><p class="para"' + comment['content'] + '</p></div>'; }); $('#resText').html(html); } }); }); });
上面的例子實現了一個相似於表單提交的功能。
Promise的異步:
let promise = new Promise(function(resolve, reject) { console.log('Promise'); //實例化後當即執行 resolve(); //任務(成功)完成 }); promise.then(function() { console.log('resolved.'); //任務結束執行 }); console.log('Hi!'); //在實例化promise的同時,執行
顯示順序:"Promise"---"Hi"---"resolved"
能夠看出,在promise執行的整個過程當中(實例化到結束),並無阻塞其餘外部語句的執行,換句話說,其餘語句
不用等到輸出"resolved"以後再執行。
function loadImageAsync(url) { return new Promise(function(resolve, reject) { const image = new Image(); image.onload = function() { resolve(image); //promise對象狀態變爲resolved }; image.onerror = function() { reject(new Error('Could not load image at ' + url)); }; //promise對象狀態變爲rejected並拋出錯誤 image.src = url; }); }
注意:上面狀態改變時傳入函數的參數(image、new Error),會傳到以後then函數,做爲then函數的參數的參數!!!
loadImageAsync(url).then( function(success){console.log(success);} ,function(error){console.log(error);});
這裏的success接收來自resolved狀態的參數image,error接收來自rejected狀態的參數new Error。
事實上then後面還能夠加上一個catch函數用來捕捉rejected狀態產生的錯誤,這樣就能夠省略掉then函數裏面的第二個參數
promise.then(success()).catch(error()).finally(function(){});
看上去是否是相似於java的try...catch...finally呢?
其餘方法請戳===>Promise。
18.Iterator接口
具有Iterator接口的原生數據結構:
Array---Map---Set---String---TypedArray---NodeList對象---函數的arguments對象。
實用場景:
解構賦值:let [x,y] = new Set([1,2,3]) //x=1;y=2
擴展運算符:[...iterable] //將實現Iterator接口的對象轉化爲數組
yield*:yield*[2,3,4]---yield 2;yield 3;yield 4; //generator函數內部
....
實現了Iterator接口的數據類型,都會有一個屬性[Symbol.iterator],固定寫法,它是一個函數,返回一個遍歷器對象
e.g: let arr = ['a', 'b', 'c']; let iter = arr[Symbol.iterator](); //返回一個遍歷器 iter.next() // { value: 'a', done: false } iter.next() // { value: 'b', done: false } iter.next() // { value: 'c', done: false } iter.next() // { value: undefined, done: true }
注意:
for...in循環:只能獲取對象的鍵名
for...of循環:能夠得到鍵值,只返回具備數字索引的屬性(鍵或值)
var arr = ['a', 'b', 'c', 'd']; for (let a in arr) { console.log(a); // 0 1 2 3 } for (let a of arr) { console.log(a); // a b c d }
19.Generator函數補充
let a =function*(){ yield 3; yield 4; yield 5; return 6; }; console.log([...a()]); //[3,4,5]
只有執行a().next(),函數內部的語句纔會執行一次,每調用一次next()函數執行一次內部函數。
e.g:
function* dataConsumer() { console.log('Started'); console.log(`1. ${yield}`); console.log(`2. ${yield}`); return 'result'; } let genObj = dataConsumer(); genObj.next(); // Started;執行了第一條語句 genObj.next('a') // 1. a;執行了第二條語句 genObj.next('b') // 2. b;執行了第三條語句
next()函數有一個可選參數,用來表示上一次yield表達式值。
e.g:
function* foo(x) { var y = 2 * (yield (x + 1)); var z = yield (y / 3); return (x + y + z); } var b = foo(5); b.next() // { value:6, done:false } b.next(12) // { value:8, done:false } b.next(13) // { value:42, done:true }
解析:
第一次next(),x=5,那麼yield(x+1)=6---{value:6,done:false}
第二次next(12),令yield(x+1)=12,那麼y=24,輸出yield(y/3)=8---{value:8,done:false}
第三次next(13),令yield(y/3)=13,前面yield(x+1)=12,那麼最終z=13,y=24,x=5,return (x+y+z)=42---{value:42,done:true}
throw:
兩種throw:遍歷器對象的throw(),全局命令throw
iter.throw(error),這個錯誤會被遍歷器函數內部的catch捕獲,
iter.throw(error),遍歷器對象再次拋出錯誤,因爲內部的catch已經執行了,那麼此次的error會被外部的catch捕獲
throw new Error(error),這是個全局命令,會被全局(外部)做用域的catch捕獲,遍歷器對象內部的catch是不能捕獲的
遍歷器拋出的錯誤優先被遍歷器內部捕獲,內部沒有catch纔會被外部catch捕獲
①遍歷器捕捉到錯誤以後,除了執行catch內部的命令以外,還會自動執行一次next()方法。
②Generator 執行過程當中拋出錯誤,且沒有被內部捕獲,就不會再執行下去了。
若是此後還調用next方法,將返回一個value屬性等於undefined、done屬性等於true的對象。
③遍歷器的return(參數)方法會終結函數,並返回一個對象{value:參數,done:true},參數爲空,value爲undefined。
若是有finally,那麼這個return會在finally結束後執行。
④要在gen函數內部調用別的gen函數,要使用yield* gen()語句,若是沒有這個*號,那麼next().value返回的是一個遍歷器對象
20.async函數
async就表示asynchronous(異步的),async函數會返回一個Promise對象,天然可以調用其方法:
promise.then(success()).catch(error()).finally(function(){});
async function getStockPriceByName(name) { const symbol = await getStockSymbol(name); const stockPrice = await getStockPrice(symbol); return stockPrice; //stockPrice是一個promise對象 } getStockPriceByName('goog').then(function (result) { console.log(result); });
能夠看出,它和通常函數沒多大區別,只是多了一個async標識。
注意:上面所說到的返回一個對象,這個對象自己沒什麼特別,只是他能夠做爲promise對象,在調用then方法的時候做爲參數傳
到函數裏面。並且由於這個對象會被當作promisi對象,return關鍵字能夠替換成await。
21.class
class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } var a = new Point(1,2); console.log(a.x); //1 console.log(a.toString()); //(1,2) a.hasOwnProperty('x') // true a.hasOwnProperty('y') // true a.hasOwnProperty('toString') // false a.__proto__.hasOwnProperty('toString') // true
a是沒有定義toString()方法的,因此從它的原型Point上調用此方法。
繼承:extends關鍵字
class ColorPoint extends Point { constructor(x, y, color) { super(x, y); // 調用父類的constructor(x, y) this.color = color; } toString() { return this.color + ' ' + super.toString(); // 調用父類的toString() } }
繼承了父類的全部屬性,也能夠添加或者修改屬性
22.模塊化
//lib.js var counter = 3; function incCounter() { counter++; } module.exports = { counter: counter, incCounter: incCounter, };
這是一個js模塊,對外暴露兩個屬性counter(變量)、incCounter(函數),而後再去加載這個模塊
// main.js var mod = require('./lib'); console.log(mod.counter); // 3 mod.incCounter(); console.log(mod.counter); // 3
這樣就能夠去調用該模塊對外暴露的屬性了,