1. let 關鍵字:用來聲明變量;
彌補Var不足之處:
(1)let聲明的變量僅僅在自己的塊級作用域起作用,出了這個作用域就不起作用。任何一對花括號{}中的語句都屬於一個塊,在花括號裏面用let定義的所有變量在花括號外都是不可見的,稱爲塊級作用域。
(2)用var聲明變量時候會出現“變量提升”的現象;用let就不會;
使用let注意:
(1)同一個塊級作用域內,不允許重複聲明同一個變量;
(2)函數內不能用let重新聲明函數的參數
2. const關鍵字:用來聲明常量的;
常量的特點
(1)不可修改;
(2)只在塊級作用域起作用(與let關鍵詞一樣);
(3)不存在變量提升,必須先聲明後使用(與let關鍵詞一樣);
(4)不可重複聲明同一個變量;
(5)聲明後必須要賦值;
Const常量是個對象:傳址賦值
傳址:在賦值過程中,變量實際存儲的是數據地址(對數據的引用),而不是原始數據或者數據的拷貝;
var student1={“name”:”張三”};
var student2=student1;
Student2.name=”李四”;
console.log(student1);//結果:{name:”李四”}
console.log(student2);//結果:{name:”李四”}
3. ES6兼容問題
語法解析轉換工具:babel,jsx,traceur,es6-shim等
各大轉換工具、JavaScript解析引擎對ES6的支持程度情況:http://kangax.github.io/compat-table/es6
4. 新特性--解構賦值
解構:按照一定模式,從數組和對象中提取值,對變量進行賦值;
變量的賦值:
var [a,b,c]=[1,2,3];
數組的解構賦值:
(1)解構賦值可以嵌套的
(2)不完全解構:左邊與右邊不完全一樣的時候,只會給模式匹配成功的部分賦值;
(3)賦值不成功,變量的值爲undefined(相當於只聲明,沒賦值);
(4)允許默認值:var [a,b,c=3]=[1,2];
注意:當新的值爲undefined時,不會覆蓋默認值;
對象的解構賦值:
var {a,b,c}={“a”:1,”b”:2,”c”:3};
(1) 對象的賦值不會受到屬性的排列次序影響(數組會受影響);變量名和屬性名一致,纔會賦值成功;
(2) 找不到與之匹配的屬性,則賦值不成功,輸出 undefined;
(3) 對象解構賦值也可以嵌套;
(4) 可以指定默認值;
字符串的解構賦值:
var [a,b,c,d,e,f]=”我就是前端君”;
解構賦值的用途:
(1)交換變量的值
var x=1,y=2;
[x,y]=[y,x];
(2) 提取函數返回的多個值
函數只能返回一個值,我們可以將多個值裝在一個數組或對象中,再解構賦值快速提取其中的值;
(3) 定義函數變量
(4) 函數參數的默認值設定
(5) 函數參數的定義
5.字符串的擴展
新特性:模板字符
<script type="text/javascript">
let name="Jack";
let age="8歲";
let str=`write once,run anywhere`;
let ss=`My name is${name},I am${age}`;
alert(ss);
</script>
(1) 可以定義多行字符串:所有的空格和縮進都會被保留在輸出中;
(2) ${ }中可以放任何的JavaScript表達式;
${}中可以是運算表達式:${a+b };
${}中可以是對象的屬性: var obj={“a”:1,”b”:2} --${obj.a+obj.b};
${}中可以是函數的調用:${fn()};
新特性:標籤模板 常用來實現過濾用戶的非法輸入和多語言轉換;
標籤:指一個函數,一個專門處理模板字符串的函數;
<script type="text/javascript">
let name="張三";
let height=1.8;
tagFn`他叫${name},身高${height}米`;
function tagFn(arr,v1,v2) {
console.log(arr); //結果: ["他叫", ",身高", "米", raw: Array(3)]
console.log(v1);//張三
console.log(v2);//1.8
}
</script>
函數參數:第一個參數arr是數組類型,內容是除模板字符串除了${}以外的其他字符;v1是變量name的值;v2是變量height的值;
新特性:repeat函數
repeat()函數:將目標字符串重複N次,返回一個新的字符串,不影響目標字符串;
<script type="text/javascript">
let name="張三";
let name2=name.repeat(3);
console.log(name); //結果:張三
console.log(name2);//結果:張三張三張三
</script>
新特性:include
Include()函數:判斷字符串中是否含有指定的字符串,返回true表含有,false表示未含有;第二個參數選填,表示開始搜索的位置;
IndexOf()函數:通過返回是否爲-1判斷是否含有指定子字符串;
新特性:startsWith函數
StartWith()函數:判斷指定的字符串是否出現在目標字符串的開頭位置,第二個參數選填,表示開始搜索的位置;
新特性:endWith函數
endWith()函數判斷指定的字符串是否出現在目標字符串的尾部位置,第二個參數選填,表示針對前N個字符;
新特性:codePointAt函數
JavaScript無法正確讀取四字節字符,codePointAt方法可以正確識別四個字節的字符,並正確返回碼點的十進制;
charAt():返回指定位置的字符;
新特性:fromCodePointAt函數
fromCodePointAt()函數:函數參數是一個字符對應的碼點,返回的結果就是對應字符;4字節字符也能實現;
新特性:String.raw函數
String.raw():返回字符串最原始的樣貌,即使字符串中含有轉義符,都直接輸出;
Console.log(String.raw`hellp\nworld`);
6.數值擴展
全局函數移植到其他對象下:慢慢減少全局性函數,把全局函數合理地規劃到其他對象下,漸漸實現語言的模塊化;
被移植的函數-新特性:Number.isNaN 判斷傳入的是否非數值
(isNaN:is not a number)
傳統的isNaN函數會把非數值參數轉化成數值再進行判斷,而Number.isNaN只對數值有效,非數值類型參數一律返回false;(注意:當返回false時:不一定是一個數值,也可能是非數值類型的參數)
被移植的函數-新特性:Number.isFinite函數 檢查一個數值是否非無窮
非數值類型參數一律返回false,所以返回false時:不一定是一個非無窮,也可能是非數值類型參數;
被移植的函數-新特性:Number.parseInt 解析一個字符串,返回一個整數
被移植的函數-新特性:Number.parseFloat 解析一個字符串,返回一個浮點數
新增的函數-新特性:Number.isInteger 判斷是否爲整數(注意:在JavaScript內部,對整數和浮點數採用一樣的存儲方式,小數點後面是0的浮點數,會被認爲是整數)
新增的函數-新特性:極小常量Number.EPSILON 定義一個極小的數值
作用:用來判斷浮點數的計算誤差,如果浮點數的計算得到誤差 不超過Number.EPSILON 的值,就表示接受這樣的誤差;
安全整數 JavaScript能準確表示整數在-2^53到2^53之間,超過這個範圍,無法精確表示這個值,稱爲不安全;
Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER
判斷是否超過安全範圍,用Number.isSafeInteger進行判斷
Math對象新增17個函數
Math.trunc函數:用於去除一個數的小數部分,返回整數部分;
Math.sign函數:用來判斷一個數到底是正數、負數、還是零;參數是正數 結果返回1,參數是負數 返回-1,參數是0 返回0 ,參數是非數值類型的參數 返回NaN;
Math.cbrt函數:用於計算一個數的立方根;
Math.acosh(x) 返回 x 的反雙曲餘弦。
Math.asinh(x) 返回 x 的反雙曲正弦。
Math.atanh(x) 返回 x 的反雙曲正切。
Math.clz32(x) 返回 x 的 32 位二進制整數表示形式的前導 0 的個數。
Math.sinh(x) 返回x的雙曲正弦。
Math.cosh(x) 返回 x 的雙曲餘弦。
Math.expm1(x) 返回 eˆx - 1。
Math.fround(x) 返回 x 的單精度浮點數形式。
Math.hypot(...values) 返回所有參數的平方和的平方根。
Math.imul(x, y) 返回兩個參數以 32 位整數形式相乘的結果。
Math.log1p(x) 返回 1 + x 的自然對數。
Math.log10(x) 返回以 10 爲底的x的對數。
Math.log2(x) 返回以 2 爲底的 x 的對數。
Math.tanh(x) 返回 x 的雙曲正切。
7. 數組擴展
Array.of()函數 將一組值轉換成數組;
Array.from()函數 將類似數組的對象或者可遍歷的函數轉換成真正的數組;將字符串轉換成數組;
實例方法:
find()函數:找出數組中符合條件的第一個元素;不符合條件返回undefined;
<script type="text/javascript">
let arr=[1,2,4,5];
arr.find(function (value) {
return value>2;
}) // 結果:4
</script>
findIndex()函數:返回符合條件的第一個數組成員的位置;不符合條件返回-1;
fill()函數:用指定的值,填充到數組;
fill函數的參數會把原數組的每個元素填充成指定的參數。
<script type="text/javascript">
let arr=[1,2,3];
arr.fill(4,1,3);//第二個參數和第三個參數:從第1個位置到第3個位置之前填充數字4
</script>
entries()函數: 對數組的鍵值進行遍歷,返回遍歷器,可以用for...of對其進行遍歷;
<script type="text/javascript">
for(let [i,v] of ['a','b'].entries()){
console.log(i,v);
}
</script>
keys()函數:對數組的索引進行遍歷,返回遍歷器;
value()函數:對數組的元素進行遍歷,返回遍歷器;
數組推導:用簡潔的寫法,直接通過現有的數組生成新函數;(有些瀏覽器不支持推導,可以火狐瀏覽器)
<script type="text/javascript">
let arr1=[1,2,3,4];
let arr2=[for(i of arr1) if(i>3) i];
console.log(arr2);
</script>
8. 對象擴展
<script type="text/javascript">
let name="lisa";
let age="18歲";
let he={name,age}; //ES6對象的屬性寫法
console.log(he);
let he2={
say(){
alert("這是ES6的表示法"); //ES6對象的方法表示法
}
};
he2.say();
</script>
屬性名可以是表達式:用字面量定義一個對象時,可以用表達式作爲對象的屬性名或者方法名;
<script type="text/javascript">
var f="first";
var n="Name";
var s="say";
var h="Hello";
var person={
[f+n]:"zhang",
[s+h](){
return "你好嗎";
}
};
console.log(person.firstName);
console.log(person.sayHello());
</script>
新增函數:
Object.is()函數:比較兩個值是否嚴格相等,或者說全等;
Object.assign()函數:將源對象的屬性賦值到目標對象上;對象屬性出現相同名字,後面的屬性值就會覆蓋前面的屬性值;(可完成效果:給對象添加屬性和方法,克隆對象,合併多個對象,爲對象的屬性指定默認值)
Object.getPrototypeOf()函數:獲取一個對象的prototype屬性;
Object.setPrototypeOf()函數:設置一個對象的prototype屬性
模擬面向對象編程有幾個關鍵步驟:
1、構造函數;
2、給prototype對象添加屬性和方法;
3、實例化;
4、通過實例化後的對象調用類的方法或者屬性。
9. 函數擴展
參數的默認:默認參數一定放到最後,有默認值的參數後面不能再跟不需默認值的參數;
<script type="text/javascript">
function person(name='zhang',age="15") { //指定默認值
console.log(name,age);
}
person();
person("Lili",18);
</script>
rest參數:在實參中,除了第一個參數以外,剩餘的參數都會被...values獲取到;rest參數必須是函數的最後一個參數,後面不能再跟其它參數;
<script type="text/javascript">
function sum(result,...values) {
console.log(values);
values.forEach(function (v,i) {
result+=v;
});
console.log(result);
}
let res=0;
sum(res,1,2,3,4);
</script>
擴展運算符: ...(三個點) 一般結合數組使用,把數組的元素用逗號分隔開來,組成一個序列,將一個數組轉成一個對應的參數數列;
箭頭函數:(=>)一種全新的定義函數的方式:第一個a代表傳進去的參數,箭頭=>後面的a表示函數體;
<script type="text/javascript">
let sum=a=>a;
console.log(sum(5));
</script>
傳入兩個參數:如果參數超過一個,需要用小括號()括起來,函數體語句超過1條,需要用大括號{}括起來;
<script type="text/javascript">
let sum=(a,b)=>{return a+b};
console.log(sum(4,5));
</script>
▲箭頭函數的this指向定義時的this對象,而不是執行時的this對象;
10. 全新數據類型
JavaScript數據類型:
String 字符串類型
Number 數字類型
Object 對象類型
Boolean布爾值類型
Undefined未定義
全新數據類型:Symbol 解決對象的屬性名衝突
即使參數一樣,描述一樣,得到的兩個值也是不相等的;
(1)當symbol值作爲對象的屬性名的時候,不能用點運算符獲取對應的值,一定要用中括號[];
(因爲點運算會導致JavaScript把後面的屬性名理解爲一個字符串類型,而不是symbol類型)
<script type="text/javascript">
let name=Symbol();
let person={
[name]:"張三"
};
console.log(person[name]); //張三
console.log(person.name); //undefined
</script>
(2)當symbol類型的值作爲屬性名的時候,該屬性不會出現在for...in和for...of中,也不會被Object.keys()獲取到;
<script type="text/javascript">
let name=Symbol();
let person={
[name]:"張三",
age:18
};
console.log( Object.keys(person)); //["age"]
for(let key in person){
console.log(key); //age
}
</script>
(3)getOwnPropertySymbols()函數 會找到symbol類型的屬性並且返回一個數組,數組成員就是symbol類型的屬性值;
<script type="text/javascript">
let name=Symbol("name");
let age=Symbol("age");
let person={
[name]:"張三",
[age]:19
}
console.log(Object.getOwnPropertySymbols(person)); //[Symbol(name), Symbol(age)]
</script>
(4)Reflect.ownKeys() 獲取所有類型的屬性
<script type="text/javascript">
let person={
[Symbol('name')]:"張三",
"age":30
};
console.log(Reflect.ownKeys(person)); //["age", Symbol(name)]
</script>
(5)Symbol.for()函數 根據參數名,去全局環境中搜索是否以該參數爲名的symbol值,有就返回,沒有就以該參數名來創建一個新的symbol值;Symbol.for()創建的symbol值會被登記在全局環境中,供以後Symbol.for()來搜索;
(6)Symbol.keyFor()函數 返回一個以登記在全局環境的symbol值(被Symbol.for()創建的)的key,沒有就返回undefined。
11. 新特性 Proxy代理 將一個對象交給Proxy代理,然後通過編寫處理函數,來攔截目標對象的操作;
<script type="text/javascript">
let person={"name":"張三"};
var pro=new Proxy(person,{
get:function (target,property) {
return "李四"
}
});
console.log(pro.name); //李四
</script>
set方法 用於攔截對對象的寫操作;
ownKeys攔截操作,攔截過濾Object.ownKey()對對象的屬性遍歷;
<script type="text/javascript">
let person={"name":"張三","age":20,"height":180};
var pro=new Proxy(person,{
ownKeys:function (target) {
return ["name","age"]
}
});
console.log(Object.keys(person));// ["name", "age", "height"]
console.log(Object.keys(pro));// ["name", "age"]
</script>
has()攔截操作:攔截 key in object的操作,結果返回一個布爾值;用於判斷是否含有指定的鍵值對,有就返回true,否則返回false;
<script type="text/javascript">
let person={"name":"張三","age":20,"height":180};
var pro=new Proxy(person,{
has:function (target,prop) {
if(target[prop]===undefined){
return false;
}else {
return true;
}
}
});
console.log("name" in person); //true
console.log("body" in person); // false
</script>
apply()方法:被代理的變量是函數;
<script type="text/javascript">
let fn=function () {
alert("我是小王");
};
let proxy=new Proxy(fn,{
apply:function () {
alert("我不是小王")
}
});
proxy();
</script>
Proxy.revocable()取消代理函數:返回一個對象,對象中含有一個Proxy的代理實例對象,還有一個revoke屬性,是一個方法,用於取消代理;
<script type="text/javascript">
let person={"name":"張三"};
let handle={
get:function (target,prop) {
return "李四";
}
};
let object=Proxy.revocable(person,handle);
console.log(object.proxy.name); //李四
object.revoke();
console.log(object.proxy.name); //報錯
</script>
其他攔截操作
defineProperty( ) deleteProperty( ) enumerate( )
getOwnPropertyDescriptor( ) getPrototypeOf( ) isExtensible( ) preventExtensions( ) setPrototypeOf( )
12. 新特性for...of
for...of一種用於遍歷數組結構的方法,可遍歷對象包括數組,對象,字符串,set和map結構等具有iterator接口的數據結構;
for...of優勢:
(1)寫法比for循環簡潔很多;
(2)可以用break來終止整個循環,或者continute來跳出當前循環,繼續後面的循環;
(3)結合keys( )獲取到循環的索引,並且是數字類型,而不是字符串類型。
循環可以終止:
<script type="text/javascript">
var arr=[1,2,3,4,5];
for(let value of arr){
if (value == 3){
break;
}
console.log(value); //1 2
}
</script>
跳過當前循環:
<script type="text/javascript">
var arr=[1,2,3,4,5];
for(let value of arr){
if (value == 3){
continue;
}
console.log(value); //1 2 4 5
}
</script>
得到數字類型索引:
<script type="text/javascript">
var arr=[1,2,3,4,5];
for(let index of arr.keys()){
console.log(index); //0 1 2 3 4
}
</script>
遍歷字符串:
<script type="text/javascript">
let word="我是前端君";
for(let w of word){
console.log(w); //我 是 前 端 君
}
</script>
遍歷DOM.List:
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
let Plist=document.getElementsByTagName("p");
for (let p of Plist)
console.log(p); //</script>
</head>
<body>
<p>1</p>
<p>2</p>
<p>3</p>
</body>
13. ES6的Iterator遍歷器(迭代器)
for...of 不能遍歷Object對象:沒有內置遍歷器Iterator
Iterator遍歷器原理:當可遍歷對象被for...of遍歷的時候,[Symbol.iterator]()會被調用,返回一個iterator對象;其中還有一個很重要的方法:next():done的值爲false表示循環沒有結束,繼續遍歷,done的值爲true表示遍歷結束;
<script type="text/javascript">
let arr=['a','b','c'];
let iter=arr[Symbol.iterator]();
console.log(iter.next()); //{value: "a", done: false}
console.log(iter.next()); //{value: "b", done: false}
console.log(iter.next()); //{value: "c", done: false}
console.log(iter.next()); //{value: undefined, done: true}
</script>
for...of原理:先遍歷可遍歷對象的[Symbol.iterator]()方法,得到一個Iterator遍歷器對象,然後在遍歷器上不斷調用next()方法,直到done的值爲true的時候,就表示遍歷完成結束了;
自定義Iteration遍歷器
給Object對象加一個[Symbol.iterator]()方法,把一個不可遍歷的Object對象,變成可遍歷的對象:
<script type="text/javascript">
let obj={
0:"我是0",
1:"我是1",
2:"我是2",
length:3,
[Symbol.iterator]:function () {
let _this=this;
let index=0;
return{
next:()=>{
let value=_this[index];
let done=(index>=_this.length);
index++;
return {value,done}
}
}
}
};
for(let v of obj){
console.log(v); // 我是0 我是1 我是2
}
</script>
14. 特殊函數:Generator函數
Generator函數又叫生成器函數,是ES6重要的特性;
(1)普通函數用function來聲明,Generator函數用function*聲明。
(2)Generator函數內部有新的關鍵字:yield,普通函數沒有。
可以把Generator函數被調用後得到的生成器理解成一個遍歷器iterator,用於遍歷函數內部的狀態。
<script type="text/javascript">
function* Hello(name) {
yield `hello ${name}`;
yield `how are you`;
yield `bye`;
}
let ite=Hello('前端君')
console.log(Hello('前端君')); //Hello {<suspended>}
console.log(ite.next());//{value: "hello 前端君", done: false}
console.log(ite.next());//{value: "how are you", done: false}
console.log(ite.next());//{value: "bye", done: false}
console.log(ite.next());//{value: undefined, done: true}
</script>
Generator函數的行爲:
Generator函數被調用後並不會一直執行到最後,它是先回返回一個生成器對象,然後hold住不動,等到生成器對象的next( )方法被調用後,函數纔會繼續執行,直到遇到關鍵字yield後,又會停止執行,並返回一個Object對象,然後繼續等待,直到next( )再一次被調用的時候,纔會繼續接着往下執行,直到done的值爲true。
yield語句作用:
相當於暫停執行並且返回信息。有點像傳統函數的return的作用,但不同的是普通函數只能return一次,但是Generator函數可以有很多個yield。而return代表的是終止執行,yield代表的是暫停執行,後續通過調用生成器的next( )方法,可以恢復執行。
next()方法接受參數:next()的參數會作爲上一個yield的返回值 ;
關鍵詞yield* :調用另一個Generator函數,用到關鍵詞yield*;
yield* gen1();
yield* gen2();
注意:如果一個Generator函數A執行過程中,進入(調用)了另一個Generator函數B,那麼會一直等到Generator函數B全部執行完畢後,纔會返回Generator函數A繼續執行。
Generator函數的用途:
用途:可以控制函數的內部狀態,依次遍歷每個狀態;可以根據需要,輕鬆地讓函數暫停執行或者繼續執行。
根據這個特點,我們可以利用Generator函數來實現異步操作的效果。
原理是:利用Generator函數暫停執行的作用,可以將異步操作的語句寫到yield後面,通過執行next方法進行回調。
15. Set結構和Weakset
Set結構:新的數據結構,理解爲值的集合;它的值不會有重複項;Set本身是一個構造函數,可以理解爲一個類;
<script type="text/javascript">
var s=new Set([1,2,3]);
console.log(s);
var v=new Set();
v.add(1);
v.add(2);
</script>
成員值唯一:添加相同的成員值會自動忽略相同的值,只會保留一個相同的值;
size屬性:獲取成員個數
delete()方法:用戶刪除Set結構中的指定值,刪除成功返回:true,刪除失敗返回:fasle;
clear()清除所有成員;
has()方法:判斷set結構中是否含有指定的值;
entries()方法:返回一個鍵值對的遍歷器;Set結構是鍵名和鍵值是同一個值;
keys():返回鍵名的遍歷器;
values():返回鍵值的遍歷器;
forEach( )方法:遍歷每一個成員。
Set用途之一:給數組去重;
<script type="text/javascript">
let arr=[1,2,2,3,3,3,4,4];
let s=new Set(arr);
console.log(s); //{1,2,3,4}
let newArr=Array.from(s);
console.log(newArr); //[1,2,3,4]
</script>
WeakSet結構:同樣不會存儲重複的值,不同的是,它的成員必須是對象類型的值。(嚴格來說是:具有 iterable 接口的對象)
相同:WeakSet結構也提供了add( ) 方法,delete( ) 方法,has( )方法給開發者使用,作用與用法跟Set結構完全一致。
另一個不同點是:WeakSet 結構不可遍歷。因爲它的成員都是對象的弱引用,隨時被回收機制回收,成員消失。所以WeakSet 結構不會有keys( ),values( ),entries( ),forEach( )等方法和size屬性。
16. Map和WeakMap
Map基本用法:key鍵名的類型不再侷限於字符串類型,可以是各種類型是值;
<script type="text/javascript">
let m = new Map([["name","前端君"],["gender",1]]);
console.log(m);
</script>
set()方法作用:給實例設置一對鍵值對,返回Map實例;如果設置一個已經存在的鍵名,後面是鍵值會覆蓋前面的鍵值;
get()方法作用:獲取指定鍵名的鍵值,返回鍵值;不存在返回undefined;
delete()方法作用:刪除指定的鍵值對,刪除成功返回:true,否則返回:false;
clear()方法:一次刪除完所有鍵值對;
has()方法作用:判斷Map實例內是否含有指定鍵值對,有就返回true,否則返回false;
可遍歷:可以使用ES6新特性for...of遍歷鍵名或鍵值;
entries()方法:返回實例的鍵值對遍歷器;
keys()方法:返回實例所有鍵名的遍歷器;
values()方法:返回實例所有鍵值的遍歷器;
forEach()方法:遍歷每個鍵值對;
size屬性:獲取實例的成員數;
WeakMap()結構:鍵名支持引用類型的數據;(數組,對象,函數)
與Map()結構不同點:
(1)如果是普通的值類型則不允許。比如:字符串,數字,null,undefined,布爾類型。而Map結構是允許的,這就是兩者的不同之處,謹記。
(2)跟Map一樣,WeakMap也擁有get、has、delete方法,用法和用途都一樣。不同地方在於,WeakMap不支持clear方法,不支持遍歷,也就沒有了keys、values、entries、forEach這4個方法,也沒有屬性size。
(3)理由跟WeakSet結構一樣:鍵名中的引用類型是弱引用,你永遠不知道這個引用對象什麼時候會被垃圾回收機制回收了,如果這個引用類型的值被垃圾機制回收了,WeakMap實例中的對應鍵值對也會消失;
17.全新特性 Promise: 更合理,更規範處理異步操作;
Promise對象有三種狀態:
pending:剛剛創建一個Promise實例的時候,表示初始狀態;
fulfilled:resolve方法調用的時候,表示操作成功;
rejected:reject方法調用的時候,表示操作失敗;
注意:狀態只能從 初始化 -> 成功 或者 初始化 -> 失敗,不能逆向轉換,也不能在成功fulfilled 和失敗rejected之間轉換;
<script type="text/javascript">
let pro=new Promise(function (resolve,reject) { //實例後狀態:pending
if("操作成功"){
resolve(); //狀態爲:fulfilled
}else {
reject();//狀態爲:rejected
}
});
</script>
then()方法:用於綁定處理操作後的處理程序
pro.then(function (res) {
//操作成功的處理程序
},function (error) {
//操作失敗是處理程序
});
catch()方法:只接受一個參數處理操作異常後的業務;
綜合兩個方法:將then方法用於處理操作成功,catch方法用於處理操作異常;(之所以能鏈式調用,是因爲then方法和catch方法調用,都會返回promise對象)
pro.then(function (res) {
//操作成功的處理程序
}).catch(function (error) {
//操作失敗的處理程序
})
完整案例:
<script type="text/javascript">
let pro=new Promise(function (resolve,reject) { //實例後狀態:pending
if(true){
resolve("操作成功"); //狀態爲:fulfilled
}else {
reject("操作失敗");//狀態爲:rejected
}
});
pro.then(requestA).then(requestB).then(requestC).catch(requestError);
function requestA() {
console.log("請求A成功");
return '請求B,下一個就是你了';
}
function requestB(res) {
console.log("上一步的結果"+res);
console.log("請求B成功");
return '請求C,下一個就是你了';
}
function requestC(res) {
console.log("上一步的結果"+res);
console.log("請求C成功");
}
function requestError(res) {
console.log("請求失敗");
}
//打印結果:
//請求A成功
//上一步的結果:請求B,下一個就是你了
//請求B成功
//上一步的結果:請求C,下一個就是你了
//請求C成功
</script>
Promise.all()方法:接受一個數組作爲參數,數組的元素是Promise實例對象,當參數中實例對象的狀態都爲fulfilled時,Promise.all()纔會返回;
<script type="text/javascript">
let pro1=new Promise(function (resolve,reject) {
setTimeout(function () {
resolve('實例1操作成功');
},4000);
});
let pro2=new Promise(function (resolve,reject) {
setTimeout(function () {
resolve('實例1操作成功');
},2000);
})
Promise.all([pro1,pro2]).then(function (result) {
console.log(result); //延遲五秒輸出結果
})
</script>
Promise.race()方法:只要有一個狀態發生變化,就會返回,不管是成功還是失敗;
18.類的概念
基本用法:constructor構造方法是一個類必須要有的方法;
類的屬性和方法和創建實例對象:必須使用new創建來創建;先聲明定義,再創建實例,否則會報錯;
<script type="text/javascript">
class Animal{
constructor(name){ //constructor構造方法,不能含有多個constructor構造函數
this.name=name; //name屬性
}
getName(){ //自定義方法
return 'This is a'+this.name;
}
}
let dog=new Animal('dog'); // 創建實例對象
console.log(dog.name); //dog
console.log(dog.getName); //This is adog
</script>
類的靜態方法:直接使用類名即可訪問的方法;而實例方法通過實例對象來調用;
<script type="text/javascript">
class Animal{
constructor(name){ //constructor構造方法,不能含有多個constructor構造函數
this.name=name; //name屬性
}
static friends(a1,a2){
return `${a1.name} and ${a2.name} are friends`
}
}
//創建實例
let dog=new Animal('dog'); // 創建實例對象
let cat=new Animal('cat');
//調用靜態方法;
console.log(Animal.friends(dog,cat)); //dog and cat are friends
</script>
類的繼承:關鍵詞:extends實現子類繼承父類;
super:父類中的this
<script type="text/javascript">
class Animal{} //父類
class Dog extends Animal {
constructor(name, color) {
super(name); //super:父類中的this
this.color = color;
}
}
</script>
使用super有幾個要注意的事項:
(1)子類必須在constructor方法中調用super方法;
(2)必須先調用super( ),纔可以使用this,否則報錯;super( )相當於父類構造函數的調用;
<script type="text/javascript">
class Animal{
constructor(name){
this.name=name;
}
say(){
return `This is a animal`;
}
}
//子類
class Dog extends Animal {
constructor(name, color) {
super(name); //super:父類中的this
this.color = color;
}
//子類實例方法
getAttritube(){
return `${super.say()},
name:${this.name},
color:${this.color}`;
}
}
let d=new Dog("dog","black"); //創建Dog實例
console.log(d.getAttritube()); //調用子類實例
//This is a animal, name:dog, color:black
</script>
19. 缺失已久的特性:module模塊;
目前還沒有瀏覽器支持ES6的module模塊;
module模塊:一個模塊,就是一個對其他模塊暴露自己的屬性或者方法的文件;
導出Export:作爲一個模塊,可以選擇性的給其他模塊暴露(提供)自己的屬性和方法,供其他模塊使用;
//---module-B.js文件---
//導出變量:name
export var name = "前端君";
導入Import:作爲一個模塊,引入給其他模塊提供的屬性和方法,供自己模塊使用;
//---module-A.js文件---
//導入 模塊B的屬性 name
import { name } from "./module-B.js";
console.log(name)
//打印結果:前端君
批量導出:
//屬性name
var name = "前端君";
//屬性age
var age = 25;
//方法 say
var say = function(){
console.log("say hello");
}
//批量導出
export {name,age,say}
批量導入:變量名字必須跟導出的一致才能準確獲取,位置順序無要求;
//---module-A.js文件---
//導入 模塊B的屬性 name
import { name,age,say } from "./module-B.js";
console.log(name)
//打印結果:前端君
console.log(age)
//打印結果:25
say()
//打印結果:say hello
使用關鍵字as,可以實現給變量name更換名字爲myname。
import { name as myname } from "./module-B.js";
console.log(myname)
//打印結果:前端君
整體導入:使用星號符*將模塊B提供的所有屬性和方法整體導入賦值給變量obj,我們可以點運算符來獲取它的屬性和方法。
//使用*實現整體導入
import * as obj from "./module-B.js";
默認導出:每個模塊支持我們導出一個沒有名字的變量,我們使用關鍵語句export default來實現;
export default function(){
console.log("I am default Fn");
}
我們使用export default關鍵字對外導出一個匿名函數,導入這個模塊的時候,可以爲這個匿名函數取任意的名字;(同樣是使用import關鍵字導入模塊B,但是這次不需要使用大括號{ }。我們使用新的名字:sayDefault來代替導入的匿名函數,最後調用一下,打印結果正是模塊B默認導出的匿名函數的執行效果。);
//取任意名字均可
import sayDefault from "./module-B.js";
sayDefault();
//結果:I am default Fn
注意事項:
(1)聲明的變量,對外都是隻讀;但是,如果導出對象是對象類型,就可以修改;
(2)導入不存在的變量,值爲undefined;不會拋出異常;