好的代碼實踐
我們有一個方法:buildAnimal(),它需要三個參數:accessory, animal, color。
<code>function
buildAnimal
(accessory, animal, color
){...}1
/<code>
然後我們需要加一個參數,我們需要怎麼做?很簡單啊,直接在方法名後面加不就好了嗎。
但是我們是好的程序員,怎麼能這麼沒追求啊是不是:
“Functions should have a small number of arguments. No argument is best, followed by one, two, and three. More than three is very questionable and should be avoided with prejudice.”Robert C. Martin’s Clean Code
我們開始重構,把所有的參數放到一個對象裡面:animalData,它有下面三個屬性:animal, color, hairType
<code>function
buildAnimal
(animalData
){...}1
/<code>
如果要加參數,直接加到animalData的屬性裡面就好了。但是,又有一個問題了。如果我們要衝對象裡面拿數據:可能要這樣:
<code>function
buildAnimal(animalData){
let
accessory = animalData.accessory,
animal
=animalData.animal,
color
=animalData.color,
hairType
=animalData.hairType;
...
}1234567
/<code>
代碼重複了很多,很不優雅對不對!
解構
先定義一個對象:
<code>let
obj = { accessory:'horn'
, animal:'horse'
, color:'purple'
, hairType:'curly'
}123456/<code>
解構的原理是:從一個對象一次性解析出多個屬性給不同變量,比如數組中解析出元素,從map/set中解析出數據等。
模式
任何結構都有兩個部分1 解構源: 等號右邊是要解構的對象。2 解構目標:等號左邊是要解構的對象。
對象解構(解構源)
上面的例子,解構的寫法可以這樣:
<code>function
buildAnimal
(animalData
){let
{accessory, animal, color, hairType} = animalData; ... }1234
/<code>
animalData的對象屬性給到變量:accessory, animal, color, hairType
<code>/<code>/<code>/<code>/<code>console
.log(accessory);//
hornconsole
.log(animal);//
horse ... 你可能要問,如果是多層嵌套的對象怎麼解構? 比如: ```let
person = {name
:'Maya'
,age
:30
,phone
:'123'
,address
:{zipcode
:1234
,street
:'rainbow'
,number
:42
} }class
="se-preview-section-delimiter"
>div
>12345678910111213141516171819202122
我們可以這麼做:
<code>let
{address
: {zipcode, street, number}} = person;console
.log(zipcode, street, number);<
div
class
="se-preview-section-delimiter"
>div
>12345678
/<code>或者:
<code>let
{zipcode, street, number} = person.address;console
.log(zipcode, street, number);<
div
class
="se-preview-section-delimiter"
>div
>12345678
/<code>可能有人說我們需要,我們的變量名需要和屬性名一樣。實際上不需要。我們可以重新修改它的名字:比如
<code>let
{name
: fullName} = person;console
.log(fullName);console
.log(name);<
div
class
="se-preview-section-delimiter"
>div
>123456789
/<code>解構數組
比如我們定義這樣一個數組:
<code>var
arr = ["one"
,"two"
,"three"
,"four"
];class=
"se-preview-section-delimiter"
>1234567
/<code>這一次我們左邊就不能用{},而應該用[]:
<code>var
[first, second] = arr;var
[,,third, four] = arr;var
[one, two, three, four] = arrclass
="se-preview-section-delimiter"
>div
>123456789
說明:如果不要解構某一個元素,直接逗號隔開就行了,參考:【行2】。要注意的是逗號的位置和數量。解構嵌套數組:
<code>var
arr2 = [['one'
,'two'
],'three'
,'four'
];var
[[one, two]] = arr2;class=
"se-preview-section-delimiter"
>12345678
/<code>解構可遍歷的對象:比如Map,Set,字符串等
<code>var
[a, b] =new
Set
([1
,2
]);var
[a, b] =new
Map
([[1
,2
], [2
,3
]]);var
[x, y] ="xyz"
;<
div
class
="se-preview-section-delimiter"
>div
>123456789
/<code>解構賦值
多個變量的聲明和初始化:
<code>let
a,
b,
c,
d;
a
=
2
;
b
=
3
;
c
=
{
id:
4
};
d
=
5
;
//Or:
let
a
=
2
,
b
=
3
,
c
=
{
id:
4
},
d
=
5
;
class="se-preview-section-delimiter">
123456789101112
/<code>解構賦值的話,我們可以這麼寫:
<code>let
a,
b,
c,
d;
[a,
b,
c,
d]
=
[2,
3
,
{
id:
4
},
5
];
//Or:
let
[a,
b,
c,
d]
=
[2,
3
,
{
id:
4
},
5
];
class="se-preview-section-delimiter">
123456789
/<code>解構帶上默認值
如果我們要解構的對象的屬性沒有值,甚至屬性不存在。這個時候,我們需要一個默認值:通常我們可能會這麼寫:
<code>let
name = person.name ||"default name"
;class=
"se-preview-section-delimiter"
>1234567
/<code>在解構裡面,我們可以這麼寫:
<code>let
{name ="default name"
} = obj;class=
"se-preview-section-delimiter"
>1234567
/<code>如果屬性不存在,name 會被賦值一個默認的值。或者:
<code>let
{name: myFullName ="default name"
} = obj;class=
"se-preview-section-delimiter"
>1234567
/<code>如果屬性不存在,myFullName 會被賦值一個默認的值。
多參數: …操作符
比方說我們有一個數組,我們想要數組的第一個元素,剩餘的元素用作其他用途。一般我們會這麼寫:
<code>let
first = arr[0
], rest = arr.slice(1
);class=
"se-preview-section-delimiter"
>12345678
/<code>ES6解構我們可以這麼寫:
<code>let
[first, ...rest] = arr;console
.log(first);console
.log(rest);<
div
class
="se-preview-section-delimiter"
>div
>123456789
/<code>注意:…操作符只能放到最後。
<code>let
[...rest, last] = arr;class=
"se-preview-section-delimiter"
>12345678
/<code>交換
<code>function
swap
(arr, i, j
){let
temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; }class
="se-preview-section-delimiter"
>div
>1234567891011
我們經常會有上面的交換兩個元素的代碼。有了解構以後,我們可以這麼寫:
<code>function
swap
(arr, i, j
){ [arr[i], arr[j]] = [arr[j], arr[i]]; }class
="se-preview-section-delimiter"
>div
>123456789
解構在函數中的好處
在上面的例子中,我們是這麼做的:
<code>function
buildAnimal
(animalData
){let
{accessory, animal, color, hairType} = animalData;console
.log(`I'm a
${color}
${animal}
with${accessory}
and${hairType}
hair`}; }class
="se-preview-section-delimiter"
>div
>12345678910
實際上,我們希望直接從參數列表裡解構出來:
<code>function buildAnimal({accessory, animal, color, hairType}}{...}<
div
class
="se-preview-section-delimiter"
>div
> 1234567/<code>甚至可以定義默認值:
<code>function
buildAnimal
({accessory =
""
, animal ="cat"
, color ='rainbow'
, hairType ='straight'
}){...}class
="se-preview-section-delimiter"
>div
>1234567
調用的方式這樣:
<code>buildAnimal({accessory ="horn"
, animal ="horse"
, color ='purple'
, hairType ='curly'
}};class=
"se-preview-section-delimiter"
>12345678
/<code>注意一點:如果我們要默認參數,我們需要傳遞一個對象進去:
<code>buildAnimal({}); buildAnimal();class=
"se-preview-section-delimiter"
>12345678
/<code>我們能不傳遞一個空對象嗎?可以。
<code>/<code>function
buildAnimal
({accessory =
""
, animal ="cat"
, color ='rainbow'
, hairType ='straight'
} = {}){...}class
="se-preview-section-delimiter"
>div
>1234567
我們給我們的參數一個默認的值:{}
數組也是類似:
<code>function
sum
([a =
0
, b =0
, c =0
]=[]) {return
a + b + c;}console
.log(sum([1
,2
,3
]));console
.log(sum());<
div
class
="se-preview-section-delimiter"
>div
>123456789
/<code>解構不好的地方
1 我們不能解構,如果沒有采用聲明的語法,或者()包起來因為解構是以{}開頭,而{}在JavaScript中當做一個塊,而不是對象常量。
<code>let
a,
b;
{a,
b}
=
{a:
1
,
b:
2
};
//Error!!!
({a,b})
=
{a:
1
,
b:
2
};
//Error!!
({a,
b}
=
{a:
1
,
b:
2
});
//OK1234
/<code>2 嵌套對象的屬性必須存在否則會解構失敗
<code>1
我們不能解構,如果沒有采用聲明的語法,或者()包起來
因為解構是以{}開頭,而{}在JavaScript中當做一個塊,而不是對象常量。
```javascript
let
a,
b;
{a,
b}
=
{a:
1
,
b:
2
};
//Error!!!
({a,b})
=
{a:
1
,
b:
2
};
//Error!!
({a,
b}
=
{a:
1
,
b:
2
});
//OK12345678
/<code>以上就是今天的主要內容,感謝閱讀。
收藏
舉報
小生編程Loading.../<code>掃碼下載今日頭條
javascriptperson = {:{} }
/<code>關鍵字: function accessory hairType