How does the array property work in JS object
up vote
11
down vote
favorite
For the following code, why the propB
of myObj
is updated? And why test.childObj
doesn't have the own property propB
?
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log(myObj.propB.length);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
javascript
add a comment |
up vote
11
down vote
favorite
For the following code, why the propB
of myObj
is updated? And why test.childObj
doesn't have the own property propB
?
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log(myObj.propB.length);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
javascript
add a comment |
up vote
11
down vote
favorite
up vote
11
down vote
favorite
For the following code, why the propB
of myObj
is updated? And why test.childObj
doesn't have the own property propB
?
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log(myObj.propB.length);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
javascript
For the following code, why the propB
of myObj
is updated? And why test.childObj
doesn't have the own property propB
?
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log(myObj.propB.length);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log(myObj.propB.length);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log(myObj.propB.length);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
javascript
javascript
edited Nov 29 at 8:26
falinsky
3,35831942
3,35831942
asked Nov 29 at 7:57
Rick
1277
1277
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
up vote
11
down vote
accepted
Using Object.create
you do not copy an object, but you create a new object that inherits the passed one:
this.childObj { } -> myObj { propA: "", propB: }
Now when you get a property, it gets looked up in the inheritance chain. As it can't be found in the child object, it gets looked up in myObj
. That is usually not a problem, as setting an objects property directly sets it on the object itself without using the inheritance chain, therefore this:
this.childObj.propA += "test";
looks up propA
on myObj
but sets propA
on the childObj
. With reference types however, you do not rewrite the property, therefore this:
this.childObj.propB.push(1);
looks up propB
in myObj
, and pushes to that, the result is:
this.childObj { propA: "test" } -> myObj { propA: "", propB: [1] }
To resolve that, the childObj has to have its own propB
array:
this.childObj.propB = this.childObj.propB.slice();
That results in:
this.childObj { propA: "test", propB: [1] } -> myObj { propA: "", propB: [1] }
and now pushing to propB
pushes to the array in childObj
.
add a comment |
up vote
3
down vote
That is because myObj
becomes a prototype of newly created test
object (caused by creating it via Object.create.
Due to you just modify underlying prop propB
of childObj
(and not assign the new value like for propA
) you only modify the prop of prototype. Please read more about inheritance in javascript.
add a comment |
up vote
2
down vote
By using Object.create(myObj);
, myObj
becomes the prototype of childObj
. If a property is not found in an object and is found in the prototype, the one from the prototype is used. Also note that hasOwnProperty
tells if the objects owns the property itself, and will return false if it exists only in the prototype and not in the object. By assigning directly a property on an object, you set it on the object, not on the prototype, but when you modify the property propB with push, the property is not found directly in childObject, so you modify the prototype.
You have to be careful with that, as all objects created this way will share the same prototype object and by modifying one, you will modify it for all instances.
You have also to be extra careful because it can be tricky to know in javascript where in the prototype chain your property come from, as myObj also have a prototype.
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log('test: ', test);
console.log('test prototype: ', test.__proto__);
console.log('test.childObj: ', test.childObj);
console.log('test.childObj prototype: ', test.childObj.__proto__);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
add a comment |
up vote
1
down vote
Javascript inheritance does not work like in most other languages. When using var x = Object.create(someObj)
, the new object x
is actually empty (it has no properties of its own) along with a reference to its prototype: the separate object someObj
.
Any property or function that you then try to access from x
which does not resolve there, will be looked up in someObj
- or even higher up, if someObj
also has a prototype object, etc.
Things can get confusing when inherited properties are modifiable objects, as in your example. As we have seen, trying to modify the array x.propB
by pushing an item to it, will actually modify the inherited array contained in someObj
.
I'm strongly convinced that it is bad style to have modifiable objects (both arrays and regular objects) in prototype objects. Instead, prototype objects should contain only functions and no data, or at least no data beyond simple strings, numbers and booleans which are not modifiable.
To summarize:
- Functions are useful to inherit, they are not modifiable (you can't change the function body), and can still be overridden/replaced if needed.
- Data becomes shared data by all inheritors, unless/until they override it by a re-assignment, which is a burden in itself.
add a comment |
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
11
down vote
accepted
Using Object.create
you do not copy an object, but you create a new object that inherits the passed one:
this.childObj { } -> myObj { propA: "", propB: }
Now when you get a property, it gets looked up in the inheritance chain. As it can't be found in the child object, it gets looked up in myObj
. That is usually not a problem, as setting an objects property directly sets it on the object itself without using the inheritance chain, therefore this:
this.childObj.propA += "test";
looks up propA
on myObj
but sets propA
on the childObj
. With reference types however, you do not rewrite the property, therefore this:
this.childObj.propB.push(1);
looks up propB
in myObj
, and pushes to that, the result is:
this.childObj { propA: "test" } -> myObj { propA: "", propB: [1] }
To resolve that, the childObj has to have its own propB
array:
this.childObj.propB = this.childObj.propB.slice();
That results in:
this.childObj { propA: "test", propB: [1] } -> myObj { propA: "", propB: [1] }
and now pushing to propB
pushes to the array in childObj
.
add a comment |
up vote
11
down vote
accepted
Using Object.create
you do not copy an object, but you create a new object that inherits the passed one:
this.childObj { } -> myObj { propA: "", propB: }
Now when you get a property, it gets looked up in the inheritance chain. As it can't be found in the child object, it gets looked up in myObj
. That is usually not a problem, as setting an objects property directly sets it on the object itself without using the inheritance chain, therefore this:
this.childObj.propA += "test";
looks up propA
on myObj
but sets propA
on the childObj
. With reference types however, you do not rewrite the property, therefore this:
this.childObj.propB.push(1);
looks up propB
in myObj
, and pushes to that, the result is:
this.childObj { propA: "test" } -> myObj { propA: "", propB: [1] }
To resolve that, the childObj has to have its own propB
array:
this.childObj.propB = this.childObj.propB.slice();
That results in:
this.childObj { propA: "test", propB: [1] } -> myObj { propA: "", propB: [1] }
and now pushing to propB
pushes to the array in childObj
.
add a comment |
up vote
11
down vote
accepted
up vote
11
down vote
accepted
Using Object.create
you do not copy an object, but you create a new object that inherits the passed one:
this.childObj { } -> myObj { propA: "", propB: }
Now when you get a property, it gets looked up in the inheritance chain. As it can't be found in the child object, it gets looked up in myObj
. That is usually not a problem, as setting an objects property directly sets it on the object itself without using the inheritance chain, therefore this:
this.childObj.propA += "test";
looks up propA
on myObj
but sets propA
on the childObj
. With reference types however, you do not rewrite the property, therefore this:
this.childObj.propB.push(1);
looks up propB
in myObj
, and pushes to that, the result is:
this.childObj { propA: "test" } -> myObj { propA: "", propB: [1] }
To resolve that, the childObj has to have its own propB
array:
this.childObj.propB = this.childObj.propB.slice();
That results in:
this.childObj { propA: "test", propB: [1] } -> myObj { propA: "", propB: [1] }
and now pushing to propB
pushes to the array in childObj
.
Using Object.create
you do not copy an object, but you create a new object that inherits the passed one:
this.childObj { } -> myObj { propA: "", propB: }
Now when you get a property, it gets looked up in the inheritance chain. As it can't be found in the child object, it gets looked up in myObj
. That is usually not a problem, as setting an objects property directly sets it on the object itself without using the inheritance chain, therefore this:
this.childObj.propA += "test";
looks up propA
on myObj
but sets propA
on the childObj
. With reference types however, you do not rewrite the property, therefore this:
this.childObj.propB.push(1);
looks up propB
in myObj
, and pushes to that, the result is:
this.childObj { propA: "test" } -> myObj { propA: "", propB: [1] }
To resolve that, the childObj has to have its own propB
array:
this.childObj.propB = this.childObj.propB.slice();
That results in:
this.childObj { propA: "test", propB: [1] } -> myObj { propA: "", propB: [1] }
and now pushing to propB
pushes to the array in childObj
.
edited Nov 29 at 8:23
answered Nov 29 at 8:14
Jonas Wilms
53.7k42547
53.7k42547
add a comment |
add a comment |
up vote
3
down vote
That is because myObj
becomes a prototype of newly created test
object (caused by creating it via Object.create.
Due to you just modify underlying prop propB
of childObj
(and not assign the new value like for propA
) you only modify the prop of prototype. Please read more about inheritance in javascript.
add a comment |
up vote
3
down vote
That is because myObj
becomes a prototype of newly created test
object (caused by creating it via Object.create.
Due to you just modify underlying prop propB
of childObj
(and not assign the new value like for propA
) you only modify the prop of prototype. Please read more about inheritance in javascript.
add a comment |
up vote
3
down vote
up vote
3
down vote
That is because myObj
becomes a prototype of newly created test
object (caused by creating it via Object.create.
Due to you just modify underlying prop propB
of childObj
(and not assign the new value like for propA
) you only modify the prop of prototype. Please read more about inheritance in javascript.
That is because myObj
becomes a prototype of newly created test
object (caused by creating it via Object.create.
Due to you just modify underlying prop propB
of childObj
(and not assign the new value like for propA
) you only modify the prop of prototype. Please read more about inheritance in javascript.
answered Nov 29 at 8:10
falinsky
3,35831942
3,35831942
add a comment |
add a comment |
up vote
2
down vote
By using Object.create(myObj);
, myObj
becomes the prototype of childObj
. If a property is not found in an object and is found in the prototype, the one from the prototype is used. Also note that hasOwnProperty
tells if the objects owns the property itself, and will return false if it exists only in the prototype and not in the object. By assigning directly a property on an object, you set it on the object, not on the prototype, but when you modify the property propB with push, the property is not found directly in childObject, so you modify the prototype.
You have to be careful with that, as all objects created this way will share the same prototype object and by modifying one, you will modify it for all instances.
You have also to be extra careful because it can be tricky to know in javascript where in the prototype chain your property come from, as myObj also have a prototype.
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log('test: ', test);
console.log('test prototype: ', test.__proto__);
console.log('test.childObj: ', test.childObj);
console.log('test.childObj prototype: ', test.childObj.__proto__);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
add a comment |
up vote
2
down vote
By using Object.create(myObj);
, myObj
becomes the prototype of childObj
. If a property is not found in an object and is found in the prototype, the one from the prototype is used. Also note that hasOwnProperty
tells if the objects owns the property itself, and will return false if it exists only in the prototype and not in the object. By assigning directly a property on an object, you set it on the object, not on the prototype, but when you modify the property propB with push, the property is not found directly in childObject, so you modify the prototype.
You have to be careful with that, as all objects created this way will share the same prototype object and by modifying one, you will modify it for all instances.
You have also to be extra careful because it can be tricky to know in javascript where in the prototype chain your property come from, as myObj also have a prototype.
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log('test: ', test);
console.log('test prototype: ', test.__proto__);
console.log('test.childObj: ', test.childObj);
console.log('test.childObj prototype: ', test.childObj.__proto__);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
add a comment |
up vote
2
down vote
up vote
2
down vote
By using Object.create(myObj);
, myObj
becomes the prototype of childObj
. If a property is not found in an object and is found in the prototype, the one from the prototype is used. Also note that hasOwnProperty
tells if the objects owns the property itself, and will return false if it exists only in the prototype and not in the object. By assigning directly a property on an object, you set it on the object, not on the prototype, but when you modify the property propB with push, the property is not found directly in childObject, so you modify the prototype.
You have to be careful with that, as all objects created this way will share the same prototype object and by modifying one, you will modify it for all instances.
You have also to be extra careful because it can be tricky to know in javascript where in the prototype chain your property come from, as myObj also have a prototype.
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log('test: ', test);
console.log('test prototype: ', test.__proto__);
console.log('test.childObj: ', test.childObj);
console.log('test.childObj prototype: ', test.childObj.__proto__);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
By using Object.create(myObj);
, myObj
becomes the prototype of childObj
. If a property is not found in an object and is found in the prototype, the one from the prototype is used. Also note that hasOwnProperty
tells if the objects owns the property itself, and will return false if it exists only in the prototype and not in the object. By assigning directly a property on an object, you set it on the object, not on the prototype, but when you modify the property propB with push, the property is not found directly in childObject, so you modify the prototype.
You have to be careful with that, as all objects created this way will share the same prototype object and by modifying one, you will modify it for all instances.
You have also to be extra careful because it can be tricky to know in javascript where in the prototype chain your property come from, as myObj also have a prototype.
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log('test: ', test);
console.log('test prototype: ', test.__proto__);
console.log('test.childObj: ', test.childObj);
console.log('test.childObj prototype: ', test.childObj.__proto__);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log('test: ', test);
console.log('test prototype: ', test.__proto__);
console.log('test.childObj: ', test.childObj);
console.log('test.childObj prototype: ', test.childObj.__proto__);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
var myObj = { propA: '', propB: }
var fatherObj = {
childObj: null,
init: function() {
this.childObj = Object.create(myObj);
this.childObj.propA = 'A';
this.childObj.propB.push(2);
}
}
var test = Object.create(fatherObj);
test.init();
console.log('test: ', test);
console.log('test prototype: ', test.__proto__);
console.log('test.childObj: ', test.childObj);
console.log('test.childObj prototype: ', test.childObj.__proto__);
console.log(test.childObj.hasOwnProperty('propA'));
console.log(test.childObj.hasOwnProperty('propB'));
edited Nov 29 at 8:31
answered Nov 29 at 8:22
Kaddath
2,3251315
2,3251315
add a comment |
add a comment |
up vote
1
down vote
Javascript inheritance does not work like in most other languages. When using var x = Object.create(someObj)
, the new object x
is actually empty (it has no properties of its own) along with a reference to its prototype: the separate object someObj
.
Any property or function that you then try to access from x
which does not resolve there, will be looked up in someObj
- or even higher up, if someObj
also has a prototype object, etc.
Things can get confusing when inherited properties are modifiable objects, as in your example. As we have seen, trying to modify the array x.propB
by pushing an item to it, will actually modify the inherited array contained in someObj
.
I'm strongly convinced that it is bad style to have modifiable objects (both arrays and regular objects) in prototype objects. Instead, prototype objects should contain only functions and no data, or at least no data beyond simple strings, numbers and booleans which are not modifiable.
To summarize:
- Functions are useful to inherit, they are not modifiable (you can't change the function body), and can still be overridden/replaced if needed.
- Data becomes shared data by all inheritors, unless/until they override it by a re-assignment, which is a burden in itself.
add a comment |
up vote
1
down vote
Javascript inheritance does not work like in most other languages. When using var x = Object.create(someObj)
, the new object x
is actually empty (it has no properties of its own) along with a reference to its prototype: the separate object someObj
.
Any property or function that you then try to access from x
which does not resolve there, will be looked up in someObj
- or even higher up, if someObj
also has a prototype object, etc.
Things can get confusing when inherited properties are modifiable objects, as in your example. As we have seen, trying to modify the array x.propB
by pushing an item to it, will actually modify the inherited array contained in someObj
.
I'm strongly convinced that it is bad style to have modifiable objects (both arrays and regular objects) in prototype objects. Instead, prototype objects should contain only functions and no data, or at least no data beyond simple strings, numbers and booleans which are not modifiable.
To summarize:
- Functions are useful to inherit, they are not modifiable (you can't change the function body), and can still be overridden/replaced if needed.
- Data becomes shared data by all inheritors, unless/until they override it by a re-assignment, which is a burden in itself.
add a comment |
up vote
1
down vote
up vote
1
down vote
Javascript inheritance does not work like in most other languages. When using var x = Object.create(someObj)
, the new object x
is actually empty (it has no properties of its own) along with a reference to its prototype: the separate object someObj
.
Any property or function that you then try to access from x
which does not resolve there, will be looked up in someObj
- or even higher up, if someObj
also has a prototype object, etc.
Things can get confusing when inherited properties are modifiable objects, as in your example. As we have seen, trying to modify the array x.propB
by pushing an item to it, will actually modify the inherited array contained in someObj
.
I'm strongly convinced that it is bad style to have modifiable objects (both arrays and regular objects) in prototype objects. Instead, prototype objects should contain only functions and no data, or at least no data beyond simple strings, numbers and booleans which are not modifiable.
To summarize:
- Functions are useful to inherit, they are not modifiable (you can't change the function body), and can still be overridden/replaced if needed.
- Data becomes shared data by all inheritors, unless/until they override it by a re-assignment, which is a burden in itself.
Javascript inheritance does not work like in most other languages. When using var x = Object.create(someObj)
, the new object x
is actually empty (it has no properties of its own) along with a reference to its prototype: the separate object someObj
.
Any property or function that you then try to access from x
which does not resolve there, will be looked up in someObj
- or even higher up, if someObj
also has a prototype object, etc.
Things can get confusing when inherited properties are modifiable objects, as in your example. As we have seen, trying to modify the array x.propB
by pushing an item to it, will actually modify the inherited array contained in someObj
.
I'm strongly convinced that it is bad style to have modifiable objects (both arrays and regular objects) in prototype objects. Instead, prototype objects should contain only functions and no data, or at least no data beyond simple strings, numbers and booleans which are not modifiable.
To summarize:
- Functions are useful to inherit, they are not modifiable (you can't change the function body), and can still be overridden/replaced if needed.
- Data becomes shared data by all inheritors, unless/until they override it by a re-assignment, which is a burden in itself.
edited Nov 29 at 8:49
answered Nov 29 at 8:41
Peter B
12.6k51941
12.6k51941
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f53534256%2fhow-does-the-array-property-work-in-js-object%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