ES6變數解構
分享變數解構分3部分
- ES變數的宣告
- 變數的解構概念,用法,注意事項
- 可能在專案遇到的應用場景
第一部分變數的宣告
ES6之前
大家都瞭解JavaScript 中變數作用域的基本單元一直是 function,就是函式作用域, 如果建立塊級作用域的話就是要宣告立即呼叫函式
// 全域性作用域 var a = 2 // 塊級作用域, (function (){ var a = 3 console.log(a) })() console.log(a) 複製程式碼
let 宣告
es新增2個宣告變數 let ,const方式, 只要在任意塊裡用這2個宣告方式宣告的都市塊級作用域變數, var,function宣告的還是函式作用域變數,塊的標誌是{...}
這意味著我們只需要一對{ .. }
就可以建立一個作用域
var a = 2; { let a = 3 console.log( a );// 3 } console.log( a );// 2 複製程式碼
const 宣告
用於建立常量。塊級變數宣告,這個變數的值在宣告時設定之後就不允許改變。 const 宣告必須要有顯式的初始化。如果需要一個值為 undefined 的常量,就要宣告 const a = undefined 。
{ const a = 2; console.log( a );// 2 a = 3;// TypeError! } 複製程式碼
塊作用域函式
從 ES6 開始,塊內宣告的函式,其作用域在這個塊內
{ foo();// 可以這麼做! function foo() { // .. } } foo();// ReferenceError 複製程式碼
舉個列子
a = 1, 每隔1秒輸出a+1的值, 並賦值給a以此累加到值5為止
// 錯誤的 // 錯誤原因是 非同步執行時去找 i變數,此時i的值為 for (var i = 1; i<=5;i++) { setTimeout(function(){ console.log('i=>', i) }, i*1000) } // 利用之前的塊級作用域 for (var i = 1; i<=5;i++) { (function (i){ //原因相當於每次宣告一個i 來實現塊級 setTimeout(function(){ console.log('i=>', i) }, i*1000) })(i) } // 利用ES6的塊級申明 for (let i = 1;i<=5;i++) { // 相當於每次宣告 i 在塊內 setTimeout(function(){ console.log('i=>', i) }, i*1000) } 複製程式碼
let,var,const注意事項
let,var 宣告且未賦值時預設值undefined,const必須顯示宣告 不會預設undefined
letname = '張三',age var _name = '李四',_age const __name = '王五', __age// 報錯 複製程式碼
let ,const 不允許重複宣告
let a = 1 let a = 2// 報錯 複製程式碼
let ,const 必須聲明後使用,如在宣告前呼叫會報錯,var宣告前使用值預設為undefined
console.log(a)// undefined console.log(b)// 報錯 var a = 0 letb = 1 複製程式碼
連續宣告賦值可採用陣列解構
- 物件
- 陣列
- 字串
- 數字
- 布林
- 類陣列 (arguments,Dom物件)
- set, map 其中字串,數字,布林都會有個轉成物件的過過程後面有例子
第二部分變數解構
把這個功能看作是一個結構化賦值(structured assignment)方法
- 什麼變數可解構?
- 何時賦值?
- 賦什麼位置的值?
什麼變數可使用賦值解構
可迭代的變數
物件解構
我們構造了一個手動賦值,把 foo() 返回物件中的值賦給獨立變數 x 、 y 和 z , 為了實現這一點,我們(不幸地)需要一個臨時變數 tmp,或者每次都呼叫一下函式 。 之前
function bar() { return { x: 4, y: 5, z: 6 }; } var tmp = bar(), x = tmp.x, y = tmp.y, z = tmp.z; console.log( x, y, z );// 4 5 6 tmp.x 屬性值賦給了變數 x ,同樣地, tmp.y 賦給了 y , tmp.z 賦給了 z 。 複製程式碼
之後
function bar() { return { x: 4, y: 5, z: 6 }; } var { x, y, z } = bar(); console.log( x, y, z ); // 4 5 6 // 這裡可體現啦,物件賦什麼位置上的值 var {x: ban,z: bap,y: baz,} = bar() console.log(ban,bap,baz)// 4 6 5 // 先用x標識去右邊物件找到值--> 然後把值付給ban變數, source = target // 剛好與什麼物件指定值相反 -->target = source var testObj = { ban: x, bap:z, baz:y } // 所以上面的實則是 var { x:x, y:y, z:z } = bar(); // 完全體現把物件賦給陣列 var o1 = { a: 1, b: 2, c: 3 }, a2 = []; ( { a: a2[0], b: a2[1], c: a2[2] } = o1 ); console.log( a2 ); // [1,2,3] 複製程式碼
物件巢狀解構
var o1 = { x: { y: { z: 6 } } }; var { x: { y: { z: w } } } = o1; console.log( w ); // 6 複製程式碼
不只是宣告
在已經宣告的變數中應用解構賦值就是賦值操作,不只是宣告
var bar = {x: 4, y: 5,z: 6} var x , y, z ( { x, y, z } = bar ); console.log( x, y, z );// 4 5 6 複製程式碼
如果省略了 var/let/const 宣告符,就必須把 整個賦值表示式用 ( ) 括起來。因為如果不這樣做,語句左側的 {..} 作為語 句中的第一個元素就會被當作是一個塊語句而不是一個物件
賦值表示式 ( x 、 y ,z等 ) 並不必須是變數識別符號。任何合法的賦值表示式都可以。 舉個栗子
var o = {x:88,y:88,z:88}; ( { x: o.x, y: o.y, z: o.z } = bar() ); console.log( o.x, o.y, o.z ); // 4 5 6 複製程式碼
可以在解構中使用計算出的屬性表示式 舉個例子( 應用場景 )
var which = "x", o = {}; ( { [which]: o[which] } = bar() ); console.log( o.x ); // 遍歷式動態匹配 var keyArr = ['name', 'age', 'score'] var obj = { name: 'a', age: 18, score: 99 } var copyObj = {} keyArr.forEach((v)=>{ ({[v]: copyObj[v]} = obj) }) console.log(copyObj) 複製程式碼
注意事項
物件的解構的值包括繼承物件
function Parent(){ this.child = 'child' } Parent.prototype = { parent: 'parent' } // 在Object.prototype上有hasOwnProperty var obj = new Parent() var {child,parent,hasOwnProperty} =obj console.log(child, parent, hasOwnProperty) // 再次用函式驗證 function abc () {} var {hasOwnProperty:myHas} = abc console.log(myHas === Object.prototype.hasOwnProperty) // true 複製程式碼
陣列的解構賦值
賦何值 --> 陣列中提取值,按照對應位置,對變數賦值
以前,為變數賦值,只能都是指定值
var a = 1; var b = 2; var c = 3; 複製程式碼
ES6 允許寫成下面這樣。
var [a, b, c] = [1, 2, 3]; 複製程式碼
巢狀陣列進行解構
var [foo, [[bar], baz]] = [1, [[2], 3]]; console.log(foo,bar,baz)// 1,2,3 複製程式碼
預設賦值
預設引數值
多年以來我們實現這一點的方式是這樣的,
function foo(x,y) { x = x || 11; y = y || 31; console.log( x + y ); } foo();// 42 foo( 5, 6 );// 11 foo( 5 );// 36 foo( null, 6 );// 17null被強制轉換成011+6 foo( 0, 42 );// 53 <--哎呀,並非42 複製程式碼
es6 預設引數值
function foo(x = 11, y = 31) { console.log( x + y ); } foo();// 42 foo( 5, 6 );// 11 foo( 5 );// 36 foo( 5, undefined );// 36 <-- 丟了undefined foo( 5, null );// 5 <-- null被強制轉換為0 foo( undefined, 6 );// 17 <-- 丟了undefined foo( null, 6 );// 6 <-- null被強制轉換為0 foo( 0, 42 );// 42 複製程式碼
知識點: 在函式宣告中的 x = 11 更像是 x !== undefined ? x : 11 而不是常見技巧 x || 11 ,所以 在把前 ES6 程式碼轉換為 ES6 預設引數值語法的時候要格外小心。
再來看解構賦值的預設值
// 全為undefined時 var obj = [] var [a = 3, b = 6, c =7] =obj console.log(a,b,c)// 3,6,7 // 驗證 var obj = [null, false,undefined,NaN,0] var [a = 1,b = 1,c = 1,d = 1,e = 1] = obj console.log(a,b,c,d,e)// 只有c為 1 複製程式碼
字串解構
var str = '你好世界' var[a,b,c,d,length] = str console.log(a,b,c,d,length)// 你 好 世 界 4 // 中間實際有一個轉換過程 var strObj = new String('你好世界') var [aa,bb,cc,dd,length] = strObj console.log(aa,bb,cc,dd,length) 複製程式碼
數值的解構
var num = 1234 var {toString: s}= num console.log(s) // 中間實際有一個轉換過程 var numObj = new Number(1234) var {toString: s} = numObj 複製程式碼
布林的解構
var bool= false var {toString: s}= bool console.log(s) // 中間實際有一個轉換過程 var boolObj = new Boolean(1234) var {toString: s} = boolObj console.log(s) 複製程式碼
第三部分專案中應用
- 交換變數的值 在專案中我們可能會要備份一份資料來,處理邏輯 之前
let a='你好',b= '世界' console.log(a,b) a = [a,b]; b = a[0]; a = a[1]; console.log(a,b) 複製程式碼
es6
let a='你好',b= '世界'; console.log(a,b); [a,b] = [b,a]; console.log(a,b); 複製程式碼
- 需快取重置資料時 (應用場景resetCom.vue)
- 提取後臺介面引數 (應用場景apiCom.vue)
- 封裝函式需大量形參時(應用場景funcCom.vue)
程式碼地址及附件碼雲 百度雲提取碼:0uqu