To add onto what @markmoxx said, as of now (form the future!), we have new ways of destructuring. We can now rename and assign defaults in destructuring statements. Ponder this:
let obj = {a,: 5, b: 6, c: [7,8],d:[9,10]e: {f: 11, g: 12}};
let {a: first, b: second, c: arr, d: [innerFirst, innerSecond], e: {f: objFirst, g: objSecond}, h = "default1", i: [defaultArr1 = "default2", defaultArr2 = "default3"], j: {k: objDefault1 = "default4"} } = obj;
console.log(first, second, arr, innerFirst, innerSecond, objFirst, objSecond, h, defaultArr1,defaultArr2, objDefault1);
// This outputs:
5, 6, [7,8],9,10,11,12,"default1","default2","default3","default4"
So, now we have more control over destructuring assignments.
Edit: for congruence
PHP's list function is mostly for arrays (mostly). And at that, has some weird behavior (reverse assignment depending on php version, etc). Destructuring in javascript is different. Even with the renaming syntax above, you still need to know the object keys/array indices. Also (this may be a matter of preference but), destructuring in javascript has more power, in that arrays and objects can both be destructured, to any nested depth, while allowing you to rename and assign defaults. But be warned, because destructuring can easy get out of hand. Consider this example of over-zelous destructuring:
const NameView = ({context: { state: [ state, update ], id, display: {tag, size = 32, type = "text", style: { wrapper: outerouter = "card", content: innerouter = "content", banner: {wrapper: outerinner = "title",content: innerinner = "content"} } } } }) => (
<div className={outerouter}>
<input className={innerouter} type={type} maxlength={size} size={size} value={name} id={id} name={id} onChange={(e) => update(e.target.value)}/>
<div className={outerinner}>
<label for={id} className={innerinner}>{tag}</label>
</div>
</div>
)