How does object chained assignment work in javascript
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
add a comment |
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
add a comment |
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
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
javascript loops object
asked Nov 13 '18 at 2:21
user10302261
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
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);
add a comment |
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);
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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);
add a comment |
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);
add a comment |
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);
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);
answered Nov 13 '18 at 2:27
CertainPerformanceCertainPerformance
78.5k143865
78.5k143865
add a comment |
add a comment |
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);
add a comment |
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);
add a comment |
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);
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);
edited Nov 13 '18 at 2:38
answered Nov 13 '18 at 2:32
EleEle
22.7k42044
22.7k42044
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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