How does object chained assignment work in javascript










0














So I am looking at some code on this question, and I have no idea how this double assignment in one line actually works:



var deepAssign = function( base, names, value ) 
// If a value is given, remove the last name and keep it for later:
var lastName = arguments.length === 3 ? names.pop() : false;

// Walk the hierarchy, creating new objects where needed.
// If the lastName was removed, then the last object is not set yet:
for( var i = 0; i < names.length; i++ ) ; /* this line wtf? */


// If a value was given, set it to the last name:
if( lastName ) base = base[ lastName ] = value;

// Return the last object in the hierarchy:
return base;
;
var x =
deepAssign(x, ['a', 'b', 'c'])
console.log(x) /* wtf, how? => a: b: c: */


I would assume that the original 'base' object would be destroyed in the for loop and that 'base' would then just be the inner object only, but somehow the original passed in object is preserved. Can someone give a detailed explanation of what is going on inside that for loop? It really bothers me to have something that I don't understand inside my code.










share|improve this question


























    0














    So I am looking at some code on this question, and I have no idea how this double assignment in one line actually works:



    var deepAssign = function( base, names, value ) 
    // If a value is given, remove the last name and keep it for later:
    var lastName = arguments.length === 3 ? names.pop() : false;

    // Walk the hierarchy, creating new objects where needed.
    // If the lastName was removed, then the last object is not set yet:
    for( var i = 0; i < names.length; i++ ) ; /* this line wtf? */


    // If a value was given, set it to the last name:
    if( lastName ) base = base[ lastName ] = value;

    // Return the last object in the hierarchy:
    return base;
    ;
    var x =
    deepAssign(x, ['a', 'b', 'c'])
    console.log(x) /* wtf, how? => a: b: c: */


    I would assume that the original 'base' object would be destroyed in the for loop and that 'base' would then just be the inner object only, but somehow the original passed in object is preserved. Can someone give a detailed explanation of what is going on inside that for loop? It really bothers me to have something that I don't understand inside my code.










    share|improve this question
























      0












      0








      0







      So I am looking at some code on this question, and I have no idea how this double assignment in one line actually works:



      var deepAssign = function( base, names, value ) 
      // If a value is given, remove the last name and keep it for later:
      var lastName = arguments.length === 3 ? names.pop() : false;

      // Walk the hierarchy, creating new objects where needed.
      // If the lastName was removed, then the last object is not set yet:
      for( var i = 0; i < names.length; i++ ) ; /* this line wtf? */


      // If a value was given, set it to the last name:
      if( lastName ) base = base[ lastName ] = value;

      // Return the last object in the hierarchy:
      return base;
      ;
      var x =
      deepAssign(x, ['a', 'b', 'c'])
      console.log(x) /* wtf, how? => a: b: c: */


      I would assume that the original 'base' object would be destroyed in the for loop and that 'base' would then just be the inner object only, but somehow the original passed in object is preserved. Can someone give a detailed explanation of what is going on inside that for loop? It really bothers me to have something that I don't understand inside my code.










      share|improve this question













      So I am looking at some code on this question, and I have no idea how this double assignment in one line actually works:



      var deepAssign = function( base, names, value ) 
      // If a value is given, remove the last name and keep it for later:
      var lastName = arguments.length === 3 ? names.pop() : false;

      // Walk the hierarchy, creating new objects where needed.
      // If the lastName was removed, then the last object is not set yet:
      for( var i = 0; i < names.length; i++ ) ; /* this line wtf? */


      // If a value was given, set it to the last name:
      if( lastName ) base = base[ lastName ] = value;

      // Return the last object in the hierarchy:
      return base;
      ;
      var x =
      deepAssign(x, ['a', 'b', 'c'])
      console.log(x) /* wtf, how? => a: b: c: */


      I would assume that the original 'base' object would be destroyed in the for loop and that 'base' would then just be the inner object only, but somehow the original passed in object is preserved. Can someone give a detailed explanation of what is going on inside that for loop? It really bothers me to have something that I don't understand inside my code.







      javascript loops object






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 13 '18 at 2:21







      user10302261





























          2 Answers
          2






          active

          oldest

          votes


















          0














          Variable assignment can resolve to an expression (something that resolves to a particular value - that is, something that some other variable can hold). The code in the question is a confusing way of writing:



          for( var i = 0; i < names.length; i++ ) ;
          base = base[ names[i] ];



          It sets base[names[i]] to an empty object if it doesn't exist yet, and then it reassigns the object that the variable name base points to to that inner object. (The outer object that base originally referred to still exists, there is just no longer a particular variable that references it - it can still be gotten through by using standard property access from the outermost x object, though).



          If you're familiar with array methods, reduce would be more appropriate and easier to read in this situation, though: have the accumulator be the current outer object, create an inner object if it doesn't exist yet, and return the inner object to be the new accumulator on the next iteration:






          function assign(outermost, keyPath, value) 
          const lastKey = keyPath.pop();
          const innermostObj = keyPath.reduce((outer, prop) =>
          outer[prop] = outer[prop] , outermost)
          innermostObj[lastKey] = value;


          const settings = ;
          assign(settings, ['Modules', 'Video', 'Plugin'], 'JWPlayer');
          console.log(settings);








          share|improve this answer




























            0














            The following:



            base = base[ names[i] ] = base[ names[i] ] || ;


            Is translated to:



            base[ names[i] ] = base[ names[i] ] || ;
            base = base[ names[i] ];


            This loop:



            for( var i = 0; i < names.length; i++ ) 
            base = base[ names[i] ] = base[ names[i] ]


            is translated to:



            names.reduce((a, name) => (a[name] || (a[name] = )), base);


            Basically, is creating an object when the key name doesn't exist, however, is a dangerous way of checking key existence.



            This is a better approach using the operator in:



            names.reduce((a, name) => (name in a ? a[name] : (a[name] = )), base);





            share|improve this answer






















              Your Answer






              StackExchange.ifUsing("editor", function ()
              StackExchange.using("externalEditor", function ()
              StackExchange.using("snippets", function ()
              StackExchange.snippets.init();
              );
              );
              , "code-snippets");

              StackExchange.ready(function()
              var channelOptions =
              tags: "".split(" "),
              id: "1"
              ;
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function()
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled)
              StackExchange.using("snippets", function()
              createEditor();
              );

              else
              createEditor();

              );

              function createEditor()
              StackExchange.prepareEditor(
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader:
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              ,
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              );



              );













              draft saved

              draft discarded


















              StackExchange.ready(
              function ()
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53272850%2fhow-does-object-chained-assignment-work-in-javascript%23new-answer', 'question_page');

              );

              Post as a guest















              Required, but never shown
























              2 Answers
              2






              active

              oldest

              votes








              2 Answers
              2






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              0














              Variable assignment can resolve to an expression (something that resolves to a particular value - that is, something that some other variable can hold). The code in the question is a confusing way of writing:



              for( var i = 0; i < names.length; i++ ) ;
              base = base[ names[i] ];



              It sets base[names[i]] to an empty object if it doesn't exist yet, and then it reassigns the object that the variable name base points to to that inner object. (The outer object that base originally referred to still exists, there is just no longer a particular variable that references it - it can still be gotten through by using standard property access from the outermost x object, though).



              If you're familiar with array methods, reduce would be more appropriate and easier to read in this situation, though: have the accumulator be the current outer object, create an inner object if it doesn't exist yet, and return the inner object to be the new accumulator on the next iteration:






              function assign(outermost, keyPath, value) 
              const lastKey = keyPath.pop();
              const innermostObj = keyPath.reduce((outer, prop) =>
              outer[prop] = outer[prop] , outermost)
              innermostObj[lastKey] = value;


              const settings = ;
              assign(settings, ['Modules', 'Video', 'Plugin'], 'JWPlayer');
              console.log(settings);








              share|improve this answer

























                0














                Variable assignment can resolve to an expression (something that resolves to a particular value - that is, something that some other variable can hold). The code in the question is a confusing way of writing:



                for( var i = 0; i < names.length; i++ ) ;
                base = base[ names[i] ];



                It sets base[names[i]] to an empty object if it doesn't exist yet, and then it reassigns the object that the variable name base points to to that inner object. (The outer object that base originally referred to still exists, there is just no longer a particular variable that references it - it can still be gotten through by using standard property access from the outermost x object, though).



                If you're familiar with array methods, reduce would be more appropriate and easier to read in this situation, though: have the accumulator be the current outer object, create an inner object if it doesn't exist yet, and return the inner object to be the new accumulator on the next iteration:






                function assign(outermost, keyPath, value) 
                const lastKey = keyPath.pop();
                const innermostObj = keyPath.reduce((outer, prop) =>
                outer[prop] = outer[prop] , outermost)
                innermostObj[lastKey] = value;


                const settings = ;
                assign(settings, ['Modules', 'Video', 'Plugin'], 'JWPlayer');
                console.log(settings);








                share|improve this answer























                  0












                  0








                  0






                  Variable assignment can resolve to an expression (something that resolves to a particular value - that is, something that some other variable can hold). The code in the question is a confusing way of writing:



                  for( var i = 0; i < names.length; i++ ) ;
                  base = base[ names[i] ];



                  It sets base[names[i]] to an empty object if it doesn't exist yet, and then it reassigns the object that the variable name base points to to that inner object. (The outer object that base originally referred to still exists, there is just no longer a particular variable that references it - it can still be gotten through by using standard property access from the outermost x object, though).



                  If you're familiar with array methods, reduce would be more appropriate and easier to read in this situation, though: have the accumulator be the current outer object, create an inner object if it doesn't exist yet, and return the inner object to be the new accumulator on the next iteration:






                  function assign(outermost, keyPath, value) 
                  const lastKey = keyPath.pop();
                  const innermostObj = keyPath.reduce((outer, prop) =>
                  outer[prop] = outer[prop] , outermost)
                  innermostObj[lastKey] = value;


                  const settings = ;
                  assign(settings, ['Modules', 'Video', 'Plugin'], 'JWPlayer');
                  console.log(settings);








                  share|improve this answer












                  Variable assignment can resolve to an expression (something that resolves to a particular value - that is, something that some other variable can hold). The code in the question is a confusing way of writing:



                  for( var i = 0; i < names.length; i++ ) ;
                  base = base[ names[i] ];



                  It sets base[names[i]] to an empty object if it doesn't exist yet, and then it reassigns the object that the variable name base points to to that inner object. (The outer object that base originally referred to still exists, there is just no longer a particular variable that references it - it can still be gotten through by using standard property access from the outermost x object, though).



                  If you're familiar with array methods, reduce would be more appropriate and easier to read in this situation, though: have the accumulator be the current outer object, create an inner object if it doesn't exist yet, and return the inner object to be the new accumulator on the next iteration:






                  function assign(outermost, keyPath, value) 
                  const lastKey = keyPath.pop();
                  const innermostObj = keyPath.reduce((outer, prop) =>
                  outer[prop] = outer[prop] , outermost)
                  innermostObj[lastKey] = value;


                  const settings = ;
                  assign(settings, ['Modules', 'Video', 'Plugin'], 'JWPlayer');
                  console.log(settings);








                  function assign(outermost, keyPath, value) 
                  const lastKey = keyPath.pop();
                  const innermostObj = keyPath.reduce((outer, prop) =>
                  outer[prop] = outer[prop] , outermost)
                  innermostObj[lastKey] = value;


                  const settings = ;
                  assign(settings, ['Modules', 'Video', 'Plugin'], 'JWPlayer');
                  console.log(settings);





                  function assign(outermost, keyPath, value) 
                  const lastKey = keyPath.pop();
                  const innermostObj = keyPath.reduce((outer, prop) =>
                  outer[prop] = outer[prop] , outermost)
                  innermostObj[lastKey] = value;


                  const settings = ;
                  assign(settings, ['Modules', 'Video', 'Plugin'], 'JWPlayer');
                  console.log(settings);






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 13 '18 at 2:27









                  CertainPerformanceCertainPerformance

                  78.5k143865




                  78.5k143865























                      0














                      The following:



                      base = base[ names[i] ] = base[ names[i] ] || ;


                      Is translated to:



                      base[ names[i] ] = base[ names[i] ] || ;
                      base = base[ names[i] ];


                      This loop:



                      for( var i = 0; i < names.length; i++ ) 
                      base = base[ names[i] ] = base[ names[i] ]


                      is translated to:



                      names.reduce((a, name) => (a[name] || (a[name] = )), base);


                      Basically, is creating an object when the key name doesn't exist, however, is a dangerous way of checking key existence.



                      This is a better approach using the operator in:



                      names.reduce((a, name) => (name in a ? a[name] : (a[name] = )), base);





                      share|improve this answer



























                        0














                        The following:



                        base = base[ names[i] ] = base[ names[i] ] || ;


                        Is translated to:



                        base[ names[i] ] = base[ names[i] ] || ;
                        base = base[ names[i] ];


                        This loop:



                        for( var i = 0; i < names.length; i++ ) 
                        base = base[ names[i] ] = base[ names[i] ]


                        is translated to:



                        names.reduce((a, name) => (a[name] || (a[name] = )), base);


                        Basically, is creating an object when the key name doesn't exist, however, is a dangerous way of checking key existence.



                        This is a better approach using the operator in:



                        names.reduce((a, name) => (name in a ? a[name] : (a[name] = )), base);





                        share|improve this answer

























                          0












                          0








                          0






                          The following:



                          base = base[ names[i] ] = base[ names[i] ] || ;


                          Is translated to:



                          base[ names[i] ] = base[ names[i] ] || ;
                          base = base[ names[i] ];


                          This loop:



                          for( var i = 0; i < names.length; i++ ) 
                          base = base[ names[i] ] = base[ names[i] ]


                          is translated to:



                          names.reduce((a, name) => (a[name] || (a[name] = )), base);


                          Basically, is creating an object when the key name doesn't exist, however, is a dangerous way of checking key existence.



                          This is a better approach using the operator in:



                          names.reduce((a, name) => (name in a ? a[name] : (a[name] = )), base);





                          share|improve this answer














                          The following:



                          base = base[ names[i] ] = base[ names[i] ] || ;


                          Is translated to:



                          base[ names[i] ] = base[ names[i] ] || ;
                          base = base[ names[i] ];


                          This loop:



                          for( var i = 0; i < names.length; i++ ) 
                          base = base[ names[i] ] = base[ names[i] ]


                          is translated to:



                          names.reduce((a, name) => (a[name] || (a[name] = )), base);


                          Basically, is creating an object when the key name doesn't exist, however, is a dangerous way of checking key existence.



                          This is a better approach using the operator in:



                          names.reduce((a, name) => (name in a ? a[name] : (a[name] = )), base);






                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Nov 13 '18 at 2:38

























                          answered Nov 13 '18 at 2:32









                          EleEle

                          22.7k42044




                          22.7k42044



























                              draft saved

                              draft discarded
















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid


                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.

                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function ()
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53272850%2fhow-does-object-chained-assignment-work-in-javascript%23new-answer', 'question_page');

                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              這個網誌中的熱門文章

                              How to read a connectionString WITH PROVIDER in .NET Core?

                              In R, how to develop a multiplot heatmap.2 figure showing key labels successfully

                              Museum of Modern and Contemporary Art of Trento and Rovereto