I am looking for a way to modify an object that was defined by a literal without passing it into another function.
example:
let o = {a:1,b:2}
console.log(o.a===3)
i thought when i define an object using a literal the the Object constructor would be called, so i did override Object.prototype.constructor but it only gets called when i do new Object({a:1,b:2})
question in simpler terms can anyone make a=3 without passing the object o to a function or a proxy or using o.a=3 or with keyword, where o is defined using an object literal?
Just do o.a=3; and console log o:
let o = {a:1,b:2};
o.a=3;
console.log(o);
Currently you are doing o.a===3 which will return Boolean value instead of overwriting the value of property a.
You also cannot do o.a=3 inside console.log() because o.a=3 will return the assigned value which is 3 but it will still change the property a of o to 3.
let o = {
a: 1,
b: 2
};
//won't print o but changes o.a to 3
console.log(o.a = 3);
It's simply not possible.
There is no constructor of an object literal.
You can create objects in different ways:
via an object literal or
via a constructor function or
via Object.create
Also, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer
question in simpler terms can anyone make a=3 without passing the object o to a function or a proxy?
o.a = 3;
I am looking for a way to modify an object that was defined by a literal without passing it into another function.
Thats impossible, cause if it would be possible you could break every piece of javascript. And that would be terrible.
Oh wait, this is JS...
with({ get o() { return { a: 3 }; }, set o(v) {} }) {
o = {a:1,b:2};
console.log(o.a===3) // true
}
What you want to achieve could be done if o.a holds a reference to the variable a - which unfortunately only works the way you'd like for variables that are passed by reference. Primitive types like String, Number and Boolean though, are passed by value.
Check the examples below:
var a = 1;
var o = { a: a };
a = 2;
console.log(o.a, a);
It also doesn't help to use an Object constructor like new Number() because that does return a reference to an object (which is passed by reference as you'd need), but assigning a new value to it reading the value still returns a primitive (which is, again, passed by value):
var a = new Number(1);
var o = { a: a.valueOf() };
a = Number(2);
console.log(o.a, a);
If you pass something that is naturally passed by reference, your expectation is fulfilled:
var a = [ 1 ]
var o = { a: a }
a[0] = 2
console.log(o.a[0])
Related
Essentially, I want to be able to access an object's property by reference. Take a look at the code below;
class Point{
x:number;
y:number;
constructor(x,y)
{
this.x=x;
this.y=y;
}
}
const a = { first: new Point(8,9), second: new Point(10,12) };
let someBool = true;
function modifyProperty(a) {
let c = someBool? a.first: a.second;
let newPoint = new Point(0,0);
c = newPoint; // Doesn't work
someBool = !someBool;
}
modifyProperty(a);
console.log(a.first);
In this example, whenever I call modifyProperty() I want to alternate between changing one of the two properties in 'a'.
However, when I assign 'c' to either 'a.first' or 'a.second', it only passes by value. The only way I could think to fix this is by making the property itself an object, like this:
const a = { first: {value: new Point(8,9)}, second: {value: new Point(10,12)} };
And then I would just call c.value = newPoint instead. This would work, but it's not a good solution, since you'd have to do this for every property in an object.
Is there no way better way to get these properties by reference? I know JS only supports pass-by-reference for objects and arrays, but what about instances of classes?
I know when Babel converts a class to normal Javascript they're treated like functions, but a function is not a primitive type - it's an object that is callable, so doesn't this work, and what would be a solution?
However, when I assign 'c' to either 'a.first' or 'a.second', it only passes by value
Yes, assignment always changes the value of the thing on the left side of =,
there is no way to change it in Javascript or TypeScript.
One workaround is to use property name together with the object to which the property belongs, instead of reference:
type Pair<T> = { first: T, second: T }
function modifyProperty(a: Pair<Point>) {
let c: keyof Pair<Point> = someBool? 'first' : 'second';
// keyof Pair<Point> type annotation means
// that only property names of Pair could be assigned to c
let newPoint = new Point(0,0);
a[c] = newPoint;
someBool = !someBool;
}
I was reading somewhere that when we pass an object into a function "...JavaScript always uses the Object by reference when it passes as argument..." What I think this implies is (correct me if I'm wrong) is that if the function was to modify the object in some way, it would change the original defined object. I tried illustrating this with some code and it does do what I think it does but when I try the example in the blog post with a Number obj, it doesn't change the original value in that object. Please see my jsbin: https://jsbin.com/wociro/edit?js,console,output
console.clear();
/**myobject Object**/
function myobject() {
this.value = 5;
}
var o = new myobject();
console.log("Original value of o: " + o.value); // o.value = 5
function objectchanger(fnc) {
fnc.value = 6;
}
objectchanger(o);
console.log("New value of o: " + o.value); // o.value is now equal to 6
/*Number Object*/
var num2 = new Number(2);
console.log("Original value of num2: " + num2);
function numberChanger(fnc) {
return fnc + 1;
}
console.log("num2 after running numberChanger: " + numberChanger(num2));
console.log("New value of num2: " + num2); //looks the same
Am I missing something?
Number objects are still objects. So their value is a reference, and if a function alters a property of an object passed as an argument, that object will be affected outside the function.
function changer(obj) {
obj.foo = 'bar';
}
var num = new Number(123);
console.log(num.foo); // undefined
changer(num);
console.log(num.foo); // 'bar'
However, the value wrapped inside the number object is not stored as a property. It's stored as a [[NumberData]] internal slot. ECMAScript provides no way to alter that slot, so you can't change the number.
Your attempt of fnc+1 unwraps the number object to get its [[NumberData]], and adds 1 to that. But the result is just discarded, it's not stored back in the [[NumberData]] slot of fnc.
If you want to be able to achieve something analogous to changing the [[NumberData]], you can
function MyNumber(num) {
this.__number__ = +num;
}
MyNumber.prototype = Object.create(Number.prototype);
Object.getOwnPropertyNames(Number.prototype).forEach(function(prop) {
var desc = Object.getOwnPropertyDescriptor(Number.prototype, prop);
if(desc && desc.value && typeof desc.value == 'function') {
var native = desc.value;
desc.value = function() {
return native.apply(this.__number__, arguments);
};
Object.defineProperty(MyNumber.prototype, prop, desc);
}
});
var num = new MyNumber(123);
console.log(+num, num+'', num.toFixed(2)); // 123, "123", "123.00"
num.__number__ = 456;
console.log(+num, num+'', num.toFixed(2)); // 456, "456", "456.00"
I actually had a lot issues when I started getting into the object side of JavaScript myself. Best way I can explain is by these examples.
Objects link.
var obj = {a: 5};
var b = obj.a;
b = 2;
// obj.a: 2
// b: 2
This will link to the object value I believe. So if you change b it will also change obj.a.
HTML DOM object link with odd behavior
var x = document.getElementById("some_div_id");
x.innerHTML = "example"; // this works
var x = document.getElementById("some_div_id").innerHTML;
x = "example"; // this doesn't, it thinks that it's document.getElementById("some_div_id");
Took me time to figure what was wrong when I first did the second DOM method.
Variables are not linked but copied.
var a = 5;
var b = a;
b = 2;
// a: 5
// b: 2
As you can see, this doesn't link the value but creates a new one based from it.
Deep copying from objects trick.
function deepCopy(objValue) {
return JSON.parse(JSON.stringify(objValue));
}
var obj = {a: 5};
var b = deepCopy(obj.a);
b = 2;
// obj.a: 5
// b: 2
This was a trick given to me some time back when I had issues wanting a object value being stored in a variable and edited but without it being linked to the object value. After a while I found I never needed it after improving my coding skills.
Also last note. I read somewhere in clean JavaScript coding that you shouldn't need to use the new object method unless it's a Date() object or or simulated class, or you may run into typeof and value check issues with ===.
Can't be certain if this is error free but hope this helps explains better.
In Javascript, objects refer to an array, indicated by [] or an object {}. You can verify the type of the variable by using typeof. These are passed by reference.
typeof [2, 5, 3] //object
typeof { a: 10} // object
If you pass the object literal to a function and modify the value of the property 'a', it would result in the value being modified.
This question already has answers here:
Is JavaScript a pass-by-reference or pass-by-value language?
(33 answers)
Closed 3 years ago.
Does JavaScript pass by references or pass by values?
Here is an example from JavaScript: The Good Parts. I am very confused about the my parameter for the rectangle function. It is actually undefined, and redefined inside the function. There are no original reference. If I remove it from the function parameter, the inside area function is not able to access it.
Is it a closure? But no function is returned.
var shape = function (config) {
var that = {};
that.name = config.name || "";
that.area = function () {
return 0;
};
return that;
};
var rectangle = function (config, my) {
my = my || {};
my.l = config.length || 1;
my.w = config.width || 1;
var that = shape(config);
that.area = function () {
return my.l * my.w;
};
return that;
};
myShape = shape({
name: "Unhnown"
});
myRec = rectangle({
name: "Rectangle",
length: 4,
width: 6
});
console.log(myShape.name + " area is " + myShape.area() + " " + myRec.name + " area is " + myRec.area());
Primitives are passed by value, and Objects are passed by "copy of a reference".
Specifically, when you pass an object (or array) you are (invisibly) passing a reference to that object, and it is possible to modify the contents of that object, but if you attempt to overwrite the reference it will not affect the copy of the reference held by the caller - i.e. the reference itself is passed by value:
function replace(ref) {
ref = {}; // this code does _not_ affect the object passed
}
function update(ref) {
ref.key = 'newvalue'; // this code _does_ affect the _contents_ of the object
}
var a = { key: 'value' };
replace(a); // a still has its original value - it's unmodfied
update(a); // the _contents_ of 'a' are changed
Think of it like this:
Whenever you create an object in ECMAscript, this object is formed in a mystique ECMAscript universal place where no man will ever be able to get. All you get back is a reference to that object in this mystique place.
var obj = { };
Even obj is only a reference to the object (which is located in that special wonderful place) and hence, you can only pass this reference around. Effectively, any piece of code which accesses obj will modify the object which is far, far away.
My two cents.... It's irrelevant whether JavaScript passes parameters by reference or value. What really matters is assignment vs. mutation.
I wrote a longer, more detailed explanation in this link.
When you pass anything (whether that be an object or a primitive), all JavaScript does is assign a new variable while inside the function... just like using the equal sign (=).
How that parameter behaves inside the function is exactly the same as it would behave if you just assigned a new variable using the equal sign... Take these simple examples.
var myString = 'Test string 1';
// Assignment - A link to the same place as myString
var sameString = myString;
// If I change sameString, it will not modify myString,
// it just re-assigns it to a whole new string
sameString = 'New string';
console.log(myString); // Logs 'Test string 1';
console.log(sameString); // Logs 'New string';
If I were to pass myString as a parameter to a function, it behaves as if I simply assigned it to a new variable. Now, let's do the same thing, but with a function instead of a simple assignment
function myFunc(sameString) {
// Reassignment... Again, it will not modify myString
sameString = 'New string';
}
var myString = 'Test string 1';
// This behaves the same as if we said sameString = myString
myFunc(myString);
console.log(myString); // Again, logs 'Test string 1';
The only reason that you can modify objects when you pass them to a function is because you are not reassigning... Instead, objects can be changed or mutated.... Again, it works the same way.
var myObject = { name: 'Joe'; }
// Assignment - We simply link to the same object
var sameObject = myObject;
// This time, we can mutate it. So a change to myObject affects sameObject and visa versa
myObject.name = 'Jack';
console.log(sameObject.name); // Logs 'Jack'
sameObject.name = 'Jill';
console.log(myObject.name); // Logs 'Jill'
// If we re-assign it, the link is lost
sameObject = { name: 'Howard' };
console.log(myObject.name); // Logs 'Jill'
If I were to pass myObject as a parameter to a function, it behaves as if I simply assigned it to a new variable. Again, the same thing with the exact same behavior but with a function.
function myFunc(sameObject) {
// We mutate the object, so the myObject gets the change too... just like before.
sameObject.name = 'Jill';
// But, if we re-assign it, the link is lost
sameObject = {
name: 'Howard'
};
}
var myObject = {
name: 'Joe'
};
// This behaves the same as if we said sameObject = myObject;
myFunc(myObject);
console.log(myObject.name); // Logs 'Jill'
Every time you pass a variable to a function, you are "assigning" to whatever the name of the parameter is, just like if you used the equal = sign.
Always remember that the equals sign = means assignment.
And passing a parameter to a function also means assignment.
They are the same and the two variables are connected in exactly the same way.
The only time that modifying a variable affects a different variable is when the underlying object is mutated.
There is no point in making a distinction between objects and primitives, because it works the same exact way as if you didn't have a function and just used the equal sign to assign to a new variable.
Function arguments are passed either by-value or by-sharing, but never ever by reference in JavaScript!
Call-by-Value
Primitive types are passed by-value:
var num = 123, str = "foo";
function f(num, str) {
num += 1;
str += "bar";
console.log("inside of f:", num, str);
}
f(num, str);
console.log("outside of f:", num, str);
Reassignments inside a function scope are not visible in the surrounding scope.
This also applies to Strings, which are a composite data type and yet immutable:
var str = "foo";
function f(str) {
str[0] = "b"; // doesn't work, because strings are immutable
console.log("inside of f:", str);
}
f(str);
console.log("outside of f:", str);
Call-by-Sharing
Objects, that is to say all types that are not primitives, are passed by-sharing. A variable that holds a reference to an object actually holds merely a copy of this reference. If JavaScript would pursue a call-by-reference evaluation strategy, the variable would hold the original reference. This is the crucial difference between by-sharing and by-reference.
What are the practical consequences of this distinction?
var o = {x: "foo"}, p = {y: 123};
function f(o, p) {
o.x = "bar"; // Mutation
p = {x: 456}; // Reassignment
console.log("o inside of f:", o);
console.log("p inside of f:", p);
}
f(o, p);
console.log("o outside of f:", o);
console.log("p outside of f:", p);
Mutating means to modify certain properties of an existing Object. The reference copy that a variable is bound to and that refers to this object remains the same. Mutations are thus visible in the caller's scope.
Reassigning means to replace the reference copy bound to a variable. Since it is only a copy, other variables holding a copy of the same reference remain unaffected. Reassignments are thus not visible in the caller's scope like they would be with a call-by-reference evaluation strategy.
Further information on evaluation strategies in ECMAScript.
As with C, ultimately, everything is passed by value. Unlike C, you can't actually back up and pass the location of a variable, because it doesn't have pointers, just references.
And the references it has are all to objects, not variables. There are several ways of achieving the same result, but they have to be done by hand, not just adding a keyword at either the call or declaration site.
JavaScript is pass by value.
For primitives, primitive's value is passed. For Objects, Object's reference "value" is passed.
Example with Object:
var f1 = function(inputObject){
inputObject.a = 2;
}
var f2 = function(){
var inputObject = {"a": 1};
f1(inputObject);
console.log(inputObject.a);
}
Calling f2 results in printing out "a" value as 2 instead of 1, as the reference is passed and the "a" value in reference is updated.
Example with primitive:
var f1 = function(a){
a = 2;
}
var f2 = function(){
var a = 1;
f1(a);
console.log(a);
}
Calling f2 results in printing out "a" value as 1.
In the interest of creating a simple example that uses const...
const myRef = { foo: 'bar' };
const myVal = true;
function passes(r, v) {
r.foo = 'baz';
v = false;
}
passes(myRef, myVal);
console.log(myRef, myVal); // Object {foo: "baz"} true
In practical terms, Alnitak is correct and makes it easy to understand, but ultimately in JavaScript, everything is passed by value.
What is the "value" of an object? It is the object reference.
When you pass in an object, you get a copy of this value (hence the 'copy of a reference' that Alnitak described). If you change this value, you do not change the original object; you are changing your copy of that reference.
"Global" JavaScript variables are members of the window object. You could access the reference as a member of the window object.
var v = "initialized";
function byref(ref) {
window[ref] = "changed by ref";
}
byref((function(){for(r in window){if(window[r]===v){return(r);}}})());
// It could also be called like... byref('v');
console.log(v); // outputs changed by ref
Note, the above example will not work for variables declared within a function.
Without purisms, I think that the best way to emulate scalar argument by reference in JavaScript is using object, like previous an answer tells.
However, I do a little bit different:
I've made the object assignment inside function call, so one can see the reference parameters near the function call. It increases the source readability.
In function declaration, I put the properties like a comment, for the very same reason: readability.
var r;
funcWithRefScalars(r = {amount:200, message:null} );
console.log(r.amount + " - " + r.message);
function funcWithRefScalars(o) { // o(amount, message)
o.amount *= 1.2;
o.message = "20% increase";
}
In the above example, null indicates clearly an output reference parameter.
The exit:
240 - 20% Increase
On the client-side, console.log should be replaced by alert.
★ ★ ★
Another method that can be even more readable:
var amount, message;
funcWithRefScalars(amount = [200], message = [null] );
console.log(amount[0] + " - " + message[0]);
function funcWithRefScalars(amount, message) { // o(amount, message)
amount[0] *= 1.2;
message[0] = "20% increase";
}
Here you don't even need to create new dummy names, like r above.
I can't see pass-by-reference in the examples where people try to demonstrate such. I only see pass-by-value.
In the case of variables that hold a reference to an object, the reference is the value of those variables, and therefore the reference is passed, which is then pass-by-value.
In a statement like this,
var a = {
b: "foo",
c: "bar"
};
the value of the 'a' is not the Object, but the (so far only) reference to it. In other words, the object is not in the variable a - a reference to it is. I think this is something that seems difficult for programmers who are mainly only familiar with JavaScript. But it is easy for people who know also e.g. Java, C#, and C.
Objects are always pass by reference and primitives by value. Just keep that parameter at the same address for objects.
Here's some code to illustrate what I mean (try it in a JavaScript sandbox such as https://js.do/).
Unfortunately you can't only retain the address of the parameter; you retain all the original member values as well.
a = { key: 'bevmo' };
testRetain(a);
document.write(' after function ');
document.write(a.key);
function testRetain (b)
{
document.write(' arg0 is ');
document.write(arguments[0].key);
b.key = 'passed by reference';
var retain = b; // Retaining the original address of the parameter
// Address of left set to address of right, changes address of parameter
b = {key: 'vons'}; // Right is a new object with a new address
document.write(' arg0 is ');
document.write(arguments[0].key);
// Now retrieve the original address of the parameter for pass by reference
b = retain;
document.write(' arg0 is ');
document.write(arguments[0].key);
}
Result:
arg0 is bevmo arg0 is vons arg0 is passed by reference after function passed by reference
Primitives are passed by value. But in case you only need to read the value of a primitve (and value is not known at the time when function is called) you can pass function which retrieves the value at the moment you need it.
function test(value) {
console.log('retrieve value');
console.log(value());
}
// call the function like this
var value = 1;
test(() => value);
This question already has answers here:
Why isn't this object being passed by reference when assigning something else to it?
(4 answers)
Closed 8 years ago.
In the below code we are passing an object. So, according to javascript we are passing a reference and manipulating.
var a = new Number(10);
x(a);
alert(a);
function x(n) {
n = n + 2;
}
But 10 is alerted instead of 12. Why?
n is local to x and first it is set to the same reference as global a. The right hand side n + 2 is then evaluated to be a number (primitive).
The left hand side of the assignment, n, is never evaluated, it is just an identifier there. So our local variable is now set to the primitive value of the right hand side. The value referenced by a is never actually modified. See
var a = new Number(10);
x(a);
alert(a); // 10
function x(n) {
alert(typeof n); // object
n = n + 2;
alert(typeof n); // number
}
When you compute
n + 2
this results in a new "native number" even if n is indeed a Number object instance.
Assigning to n then just changes what the local variable n is referencing and doesn't change the Number object instance. You can see that with
n = new Number(10);
console.log(typeof n); // ---> "object"
console.log(n + 2); // ---> 12
console.log(typeof (n+2)); // ---> "number"
n = n + 2;
console.log(typeof n); // ---> "number"
In Javascript (or Python or Lisp) there's no way to pass the "address" of a variable so that the called function mutates it. The only thing you can do is passing a setter function... for example:
function foo(setter) {
setter(42);
}
funciton bar() {
var x = 12;
foo(function(newx){x = newx;});
console.log(x); // ---> 42
}
Let me try to answer it with examples:
function modify(obj) {
// modifying the object itself
// though the object was passed as reference
// it behaves as pass by value
obj = {c:3};
}
var a = {b:2}
modify(a);
console.log(a)
// Object {b: 2}
function increment(obj) {
// modifying the value of an attribute
// working on the same reference
obj.b = obj.b + 1;
}
var a = {b:2}
increment(a);
console.log(a)
// Object {b: 3}
function augument(obj) {
// augument an attribute
// working on the same reference
obj.c = 3;
}
var a = {b:2}
augument(a);
console.log(a)
// Object {b: 2, c: 3}
Please refer the JSFiddle for working demo.
The answer is rather simple: because ECMAScript is pass-by-value and not pass-by-reference, and your code proves that. (More precisely, it is call-by-sharing, which is a specific kind of pass-by-value.)
See Is JavaScript a pass-by-reference or pass-by-value language? for some additional insight.
ECMAScript uses pass-by-value, or more precisely, a special case of pass-by-value where the value being passed is always a pointer. This special case is also sometimes known as call-by-sharing, call-by-object-sharing or call-by-object.
It's the same convention that is used by Java (for objects), C# (by default for reference types), Smalltalk, Python, Ruby and more or less every object-oriented language ever created.
Note: some types (e.g.) Numbers are actually passed directly by value and not with an intermediary pointer. However, since those are immutable, there is no observable behavioral difference between pass-by-value and call-by-object-sharing in this case, so you can greatly simplify your mental model by simply treating everything as call-by-object-sharing. Just interpret these special cases as internal compiler optimizations that you don't need to worry about.
Here's a simple example you can run to determine the argument passing convention of ECMAScript (or any other language, after you translate it):
function isEcmascriptPassByValue(foo) {
foo.push('More precisely, it is call-by-object-sharing!');
foo = 'No, ECMAScript is pass-by-reference.';
return;
}
var bar = ['Yes, of course, ECMAScript *is* pass-by-value!'];
isEcmascriptPassByValue(bar);
console.log(bar);
// Yes, of course, ECMAScript *is* pass-by-value!,
// More precisely, it is call-by-object-sharing!
If you are familiar with C#, it is a very good way to understand the differences between pass-by-value and pass-by-reference for value types and reference types, because C# supports all 4 combinations: pass-by-value for value types ("traditional pass-by-value"), pass-by-value for reference types (call-by-sharing, call-by-object, call-by-object-sharing as in ECMAScript), pass-by-reference for reference types, and pass-by-reference for value types.
(Actually, even if you don't know C#, this isn't too hard to follow.)
struct MutableCell
{
public string value;
}
class Program
{
static void IsCSharpPassByValue(string[] foo, MutableCell bar, ref string baz, ref MutableCell qux)
{
foo[0] = "More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.";
foo = new string[] { "C# is not pass-by-reference." };
bar.value = "For value types, it is *not* call-by-sharing.";
bar = new MutableCell { value = "And also not pass-by-reference." };
baz = "It also supports pass-by-reference if explicitly requested.";
qux = new MutableCell { value = "Pass-by-reference is supported for value types as well." };
}
static void Main(string[] args)
{
var quux = new string[] { "Yes, of course, C# *is* pass-by-value!" };
var corge = new MutableCell { value = "For value types it is pure pass-by-value." };
var grault = "This string will vanish because of pass-by-reference.";
var garply = new MutableCell { value = "This string will vanish because of pass-by-reference." };
IsCSharpPassByValue(quux, corge, ref grault, ref garply);
Console.WriteLine(quux[0]);
// More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value.
Console.WriteLine(corge.value);
// For value types it is pure pass-by-value.
Console.WriteLine(grault);
// It also supports pass-by-reference if explicitly requested.
Console.WriteLine(garply.value);
// Pass-by-reference is supported for value types as well.
}
}
var a = new Number(10);
x(a);
alert(a);
function x(n) {
n = n + 2; // NOT VALID as this would essentially mean 10 = 10 + 2 since you are passing the 'value' of a and not 'a' itself
}
You need to write the following in order to get it working
var a = new Number(10);
x(a);
alert(a);
function x(n) {
a = n + 2; // reassign value of 'a' equal to the value passed into the function plus 2
}
JavaScript parameter passing works similar to that of Java. Single values are passed by value, but object attributes are passed by reference via their pointer values. A value itself will not be modified in a function, but attributes of an object would be modified.
Consider the following code:
function doThis(param1, param2) {
param1++;
if(param2 && param2.value) {
param2.value++;
}
}
var initialValue = 2;
var initialObject = {value: 2};
doThis(initialValue, initialObject);
alert(initialValue); //2
alert(initialObject.value); //3
http://jsfiddle.net/bfm01b4x/
Can someone give the best explanation of what is going on here:
var o = {
name: "jack"
};
var z = {
name: o.name
};
o = {};
alert(z.name); // expected undefined, shows "jack" instead
Are object properties just references? Destroying the object o doesn't seem to destroy the referenced object (in this case the string "jack"). Or, is it the case that the "jack" referenced by o.name is actually destroyed but that z.name created a copy of o.name?
Best
// consider this too
var o = {
foo: function () {
return "hello";
}
};
var z = {
m: o.foo
};
o = {};
alert(z.m()); // hello is displayed
You might find this more interesting.
var o = {
name: "Jack"
};
var z = {
name: o
};
//Above assignment of 'o' to z.name will create a new alias to object 'o'.
//So both 'o' and 'z.name' point to same object.
//When you change value inside 'o' it will still reflect in 'z.name'
//because both point to same object
o.name="Jill";
console.log(z.name.name); // Logs : Jill and not Jack.
// Now, here you are actually assigning a new object to 'o'.
// This means now 'o' refers to a new object. But this will no way affect
// the 'z.name' reference, it still points to same object.
o = { name : "Joe"};
console.log(z.name.name); // Logs : Jill again and not Joe
Strings are copied by value, not reference.
Even if that wasn't the cause, objects are only handled by reference so overwriting o with a reference to a new object wouldn't change any references to the old object.
Are object properties just references?
Yes and No.
They are not references in the meaning of "live updating", when you change (or delete) o.name then z.name won't be altered.
They are references in the meaning of binding some arbitrary value (with a property name) to an object. These values will exist on their own, forgotten (deleted from memory) only when no one does have a handle on them any more.
You might be interested in the overview of Objects in the EcmaScript specification.
z.name created a copy of o.name?
Yes. JavaScript differentiates between objects (with changeable properties) and primitive values (which are immutable). All of these are copied by value - there is no call-by / assign-by reference in JS - and so strictly speaking both z.name and o.name reference two different values. However the object values are so-called reference values which reference the same property-value structures in memory whenever they are copied.