變量的解構賦值(模式匹配)
... 拓展運算符 可以將數據類型變為數組
解構賦值:數組的解構賦值 對象的解構賦值
1. 前后模式必須匹配
后面的值是什么格式,前面變量聲明的也是什么格式,比如后面的值是二維數組,前面聲明的也是二維模式
案例:
let [a,[b,c]]=[1,[2,3]]; // a b c 是變量
console.log(b); //2
2. 前多后少
前面聲明的變量多,后面賦值的少,解構不成功,就相當於只聲明了變量,但沒賦值,解構不成功,值都是 undefined
案例:
let [a,b]=[1]; // a b 是變量
console.log(b) // undefined
3. 前少后多
1. 省略賦值 let[,,c]=[45,12,33] // c 是變量
2. 不定參數的解構賦值,使用 ... 叫拓展運算符 ,注意事項 :拓展運算符必須寫后面
拓展運算符:...as 將后面的值以數組的形式,賦值給 as ,拓展運算符必須寫在最后
案例:
1. let [,,c]=[45,26,13] // c 是變量
console.log(c) // 13
2. let [...a]=[45,26,13]; // a 是變量
console.log(a) // 數組的形式 [45,26,13]
4. 帶有默認值問題
問題:先給默認值,在解構賦值,還是先解構賦值,如果沒有在考慮默認值?
案例分析
let [x,y=(function(){console.log("haha");return 10;})()]=[45,23];
console.log(y) //23
最終沒有輸出 haha ,說明不是先給默認值,二十先解構賦值,如果沒有,在考慮默認值
所以:解構不成功的時候,才會有默認值,沒有賦值,沒有定義
判斷一個變量有沒有定義:
var a=null; a=[ ]; a={ }; a=" " 都是定義了
var a=undefined 未定義
所以只有解構的時候,后面是 undefined 的時候,才會走默認值,否則后面給什么值就是賦值什么;
解構不成功:undefined
對象的解構賦值;
1. 變量和屬性必須同名,才可以解構賦值
2. 如果解構失敗,值是 undefined
let {name,a}={name:"zhang",age:20}; // name a 是變量
console.log(name,a) // zhang undefined
其中 name a 是變量 對象的 name age 是屬性,name變量 找到了對象的屬性 name 所以,得到值為 zhang;
a 變量,找不到對象的屬性,所以得不到值,為 undefined;
因為解構賦值,所以我們有了這樣一個新的寫法
let {ceil}=Math;
console.log(ceil(1.2)) // 2 解析這個代碼 let {ceil} = {ceil:function(){}} //這里面放的 math 對象的方法, ceil 的方法等於 ceil 的變量,所以 ceil 的變量 也擁有了相同的方法
3. 特殊情況,變量名和屬性名不一致怎么辦?
let {foo:b}={foo:"zhang"} // = 左邊: foo 是屬性 b 是變量 = 右邊:foo 是屬性
前面 foo 是屬性,后面 b 變量,解構的機制,是對應的屬性值 賦值給后面的變量
4. 對象解構的默認值問題
默認值跟數組解構的默認值是一樣的,解構成功就直接賦值,不走默認值,解構不成功,就是沒有值,或者值是 undefined 走默認值;
let {name,age=45}={name:zhang} console.log(age) // 45
let {name,age=45}={name:"zhang",age:undefined} console.log(age) //45
5. 對象解構的賦值注意點
{} 前面不能沒東西 {a}={a:12} x 這種寫法是錯的
解決:我們必須聲明 一個變量才可以:let {a}={a:12}
6. = 右邊在什么情況下,才可以解構
= 右邊的值,只要帶有 length 屬性,才可以解構,如果非要把不能解構的東西解構,轉成字符串即可
函數參數解構
函數傳對象,要在形參附一個空對象
帶 =
function fn([a,b]=[12,23]){
console.log(a+b)
}
函數參數默認值
function fn(b,v=12){
console.log(b)
}
fn(12) 前面是形參,后面是默認值,帶默認值的參數盡量要寫后面
兩句法則:
有沒有辦法解構
解構成不成功
函數參數等號左邊是形參,右邊是默認值,函數調用不傳參,走函數形參的默認值;函數調用傳參,默認值就不走了,走實參
備注:
函數作用域
函數在調用會形成私有作用域,在這個作用域下,聲明的變量和參數變量都是私有的變量,外界訪問不到同時,他在操作相同的變量是,不會操作外部的
形參的沒有變量提升,如果傳值直接賦值,所以形參有暫時性死區這一說
暫時性死區,沒有賦值,直接操作變量
函數一個類數組參數 arguments 是實參構成的集合,是一個類數組
... 拓展運算符,可將實參變成一個數組;
5. 箭頭函數
1. 箭頭函數 是適用於匿名函數
用 function 聲明的函數,是有名函數
做回調函數的時候,也是一個匿名函數
var fn=function(){} 匿名函數 做了回調函數
匿名函數的定義:只要不是關鍵字 function 聲明的函數叫匿名函數
var fn=(形參) => { 函數體 }
每個函數結束的時候一定要 return
let fn=x=>x 這種語法 : 第一個 x 代表 形參 第二個 x 代表 return 的語句
當只有一個參數,可以省略小括號;
當函數體只有一行代碼且 return xxx 的時候,可以省略 {} 和 return
箭頭函數的優勢:
1. 箭頭函數沒有 this 指向
改變 this 指向的方法
1. 在函數前 提前對 this 賦值
2. 在函數結尾處 {}.bind(this)
3. 在函數結尾處 {}.apply(this) 或 {}.call(this)
4. 使用箭頭函數
2. 箭頭函數獲取實參,不能使用arguments 用 ...arg
3. 箭頭函數不能充當類,因為 this 指向 window,而 類 的 this 指向當前實例對象
箭頭函數的 this 指向 window
函數角色
函數可以扮演 類,普通函數,function 實例對象
類:每個類身上有一個 prototype 的屬性,這個屬性是一個對象,里面有個 constructor 的屬性,屬性值是類本身
new 實例的時候,其實就是調用這個 constructor 的函數
對象,每個對象天生有個 __proto__ 的屬性
__proto__ 也是一個對象,里面有個構造函數指向他的類這個對象,也有一個 constructor 這個屬性值是他的類
對象的屬性
首先看對象中私有的屬性中,有沒有這個屬性,有就直接使用,沒有就使用 __proto__ 向他的父類的原型上查找;