分享變數解構分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
let name = '張三',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
let b = 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 ); // 17 null被強制轉換成0 11+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