javascriptdestructuring

Cannot destructure value from a DOM element when using ES6 rest


Given the below JSBIN why A is undefined?

https://jsbin.com/bisomevivu/edit?html,js,console,output

HTML:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <input data-custom="CUST" data-standard="STD" id="input">
  <button id="button">Test</test>
</body>
</html>

JS:

const [button, input] = ["button", "input"].map(id=> document.getElementById(id));

button.addEventListener("click", ()=>{
  
  const {dataset: {custom}, ...props} = input;
  const {value: A} = props;
  const {dataset: {standard}, value: B} = input;
  
  
  console.info(`A: '${A}' - B: '${B}'`);
  
});

The regular destructuring works, the rest one doesn't


Solution

  • The rest property in a destructuring assignment will only collect own properties. Not ones from the prototype.

    However, named destructuring will access any value, even from the prototype

    Simple example:

    const base = {};
    base.x = "xerophyte";
    base.y = "yumberry";
    base.z = "zucchini";
    
    const derived = Object.create(base);
    derived.a = "apple";
    derived.b = "banana";
    derived.c = "cherry";
    
    console.log(
      '"a" in derived             :', 
      "a" in derived);              //true
    console.log(
      'derived.hasOwnProperty("a"):',
      derived.hasOwnProperty("a"));
    
    
    console.log(
      '"x" in derived             :', 
      "x" in derived);             //true
    console.log(
      'derived.hasOwnProperty("x"):',
      derived.hasOwnProperty("x")); //false
      
    const {...rest} = derived;
    console.log(
      "x" in rest, //false
      "y" in rest, //false
      "z" in rest, //false
      rest,        // { "a": "apple", "b": "banana", "c": "cherry" }
    );
    
    const {a, x} = derived;
    
    console.log(a, x); //apple xerophyte
    .as-console-wrapper { max-height: 100% !important; }

    With DOM nodes, value is an inherited property for inputs:

    const input = document.querySelector("#example");
    
    console.log(
      '"value" in input             :', 
      "value" in input);              //true
    console.log(
      'input.hasOwnProperty("value"):',
      input.hasOwnProperty("value")); //false
      
    const {...rest} = input;
    console.log("value" in input); //false
    <input type="text" id="example" value="hello"/>

    Therefore, when restructuring with the rest property, the value attribute is not collected. But it is available when directly accessed as named property const {value} = input;

    See more about destructuring assignment on MDN