In the below code, I understand why person.name is changed to "john", but I do not understand fully why person does not reference undefined in memory, per the obj = undefined on the next line.
var person = { name: "wtf" };
function doStuff(obj) {
obj.name = "john";
obj = undefined;
}
doStuff(person);
person.name now equals john and person still references or "points" to the object instead of "pointing" to nothing in memory, i.e. undefined. I could carry forward in my learning and simply rely on this to work this way, but I'd never be able to articulate exactly why it works this way.
The obj parameter in your function is passed a reference to person in the function call
doStuff(person);
The parameter value is a copy of the object reference stored in person. When you give the obj variable a new value, therefore, that has no effect on person.
Related
I'm a little confused about the passing of a hash as parameter to a function.
I know that when a variable is passed to the function through a parameter, to this is applied a copy of the value.
But this is not valid with the hashes, at least not always.
Example:
var a = {b: 'hello world'};
var change = function(h){
h = true;
};
var change_v2 = function(h){
h.b = 'another hello';
};
console.log(a); // will print the original hash
change(a);
console.log(a); // naturally, will print the original hash
change_v2(a);
console.log(a); // this print b == 'another hello'
So, why the reference is used sometime for the hashes?
Can someone explain how javascript works in this case?
The simple answer to your question is that a value was copied -- a does not contain any object (what you called a hash) but actually contains a reference to the object and this reference was copied into the parameter local.
Read below for a more detailed explanation of why this happens, pass-by-value vs pass-by-reference.
In JavaScript, variables do not hold objects, they hold a reference to an object. This is an important distinction.
All parameters are pass-by-value in JavaScript. The object references stored in variables are passed by value.
These two behaviors combine to cause the specific behavior you are seeing. Let's lay out some examples of each passing behavior to prove that JavaScript passes arguments by value.
function foo(a) {
a.bar = 2;
}
var b = { bar: 1 };
foo(b);
b.bar would still be 1 if objects were passed by value, but this is not the case in JavaScript.
b.bar would be 2 if (a) the object reference was passed by value, or (b) the argument itself was passed by value.
So in this case, "pass reference by value" and "pass argument by reference" don't have a difference in behavior. Now let's introduce a case where they are different.
function foo(a) {
a = { bar: 2 };
}
var b = { bar: 1 };
foo(b);
b.bar will be 1 if the object is passed by value, which isn't what happens.
b.bar will also be 1 if the object reference is passed by value, which is what happens.
b.bar will be 2 if the argument is passed by reference.
So in summary, you have to realize two things:
Variables never contain objects, but they can contain a reference to an object. Two variables both holding a reference to the same object will reflect changes made to that object.
All arguments are passed by value, that is, the callee has no access directly to the variable that was passed in, but only to the value received by the parameter -- which can be an object reference. Manipulation of that object can cause the appearance of pass-by-reference, but note that the variable passed into the function still refers to the same object so the passed variable was not modified in any way.
As a side note, if objects were values that could be directly stored in variables, then {} === {} would be true, but it's not -- because the references are compared and found to be not equal, as these references refer to two different objects.
Javascript is pass-by-reference. Always. Assignment changes a name to refer to some value.
So,
function foo(h)
{ h = "bar"; }
The name h is a parameter to the function. The assignment affects the name h only, and that name exists only in the scope of the call to the function.
In contrast, the statement h.b = "bar"; does not assign to the name h. It assigns to the field b within the object that is referenced by the name h.
This is because JavaScript passes parameters by value.
Passing a parameter by value is like assigning formal parameters values to actual parameters. For example consider
function f(obj) { obj.a = 10; }
o = { a : 20 };
f(o);
The above code will function as if the value of o is assigned to obj like if you do
o = { a : 20 }
obj = o;
obj.a = 10;
console.log(o.a);
you will see the same effect.
See a detailed explanation here
The code below was copied and pasted from the MDN page on OOP with JavaScript. I have researched general questions on OOP with JavaScript. However, I'm a beginner and have the following questions about this code snippet:
What is the purpose of the line Person.prototype.gender = '';? If I take it out and run the code, I get the same results.
Why exactly does calling genderTeller() cause an 'undefined' alert? The MDN explanation seems a bit thin from a beginner's perspective. Is this a scope issue?
function Person(gender) {
this.gender = gender;
}
Person.prototype.gender = '';
Person.prototype.sayGender = function () {
alert(this.gender);
};
var person1 = new Person('Male');
var genderTeller = person1.sayGender;
person1.sayGender(); // alerts 'Male'
genderTeller(); // alerts undefined
alert(genderTeller === person1.sayGender); // alerts true
alert(genderTeller === Person.prototype.sayGender); // alerts true
What is the purpose of the line Person.prototype.gender = '';? If I take it out and run the code, I get the same results.
This seems to establish a default value for the gender property. With it, the property is still set even when an instance is created without calling the constructor:
var person2 = Object.create(Person.prototype);
console.log(person2.gender); // ""
Which could be useful when creating a child type:
function Employee() {}
Employee.prototype = Object.create(Person.prototype);
console.log(new Employee().gender); // ""
Why exactly does calling genderTeller() cause an 'undefined' alert?
MDN's document on this should explain it further, especially the section on "Function context." But, the value of this is determined when a function is called rather than by when or where it's defined.
By assigning person1.sayGender to genderTeller, it's being disassociated from person1. So, it's no longer a "method" of a particular object.
Instead, it's called as a regular function with the value of this being defaulted to the global object, which is window in browsers.
window.gender = 'n/a';
var genderTeller = person1.sayGender;
genderTeller(); // logs: 'n/a'
For question 1, the line
Person.prototype.gender = '';
gives the gender property a default value so that even if it is not assigned some other value when a new Person object is created, then it has a default value that is not undefined. There is a difference between '' and undefined that is important sometimes and not important other times, but there is a difference.
For question 2, when you do this:
var person1 = new Person('Male');
var genderTeller = person1.sayGender;
genderTeller(); // alerts undefined
Your variable genderTeller contains a function pointer and only a function pointer. It has NO association with your person1 object. When you call it as just a function, the this pointer inside the function will be set to either the global object (window in a browser) or undefined (if running in strict mode) and thus because this is not a Person object, this.gender will not contain an appropriate value and will likely be undefined.
There is a very important lesson in this error. In javascript, the this pointer is set according to how a method is called. When you call genderTeller(), you're just calling a function and thus there is no association whatsoever with any particular Person object. The this pointer will NOT point to a Person object and thus any references to this.xxx that assume it's a Person object will not work.
When you call person1.sayGender(), this is a very different way of calling the same function. Because you're calling it via an object reference, javascript will set the this pointer to the person1 object and it will work.
The difference between these two scenarios is subtle, but very important in javascript so I'll try to explain a bit more.
After you create your person1 object, it's an object that contains a property called sayGender. That property contains a value that points to the function for the sayGender operation. sayGender is just a function that's contained in a property (technically in the prototype chain on the person1 object, but you can just think of it as a property on that object.
When you do this:
var genderTeller = person1.sayGender;
You're creating a new variable called genderTeller that now ALSO holds a pointer to that same function. But, just like when it's in the sayGender property, it is just a function. It has no innate binding to any object. It only gets a binding to an object if you call it via an object reference (or if you use .call() or .apply() to force an object reference but that's beyond what you're doing here). When you just call
genderTeller()
you are just calling a function and it will have no object reference associated with it and thus this will not point to a Person object when the function runs.
As I mentioned above, it is possible to force an object reference. For example, you could do all of these:
var genderTeller = person1.sayGender;
genderTeller.call(person1);
// .apply() only differs from .call() in how
// arguments are passed to the function
// since you have no arguments to sayGender() it looks the same as .call()
var genderTeller = person1.sayGender;
genderTeller.apply(person1);
var genderTeller = person1.sayGender.bind(person1);
genderTeller();
And, it would again work because you were forcing an association with the person1 object when the function is called.
See MDN's reference for .call() and .apply() and .bind() if you want more info on this, but you should generally not need to use those just to call methods on an object because just calling it with the form obj.method() creates the object association and causes the this pointer to be set appropriately for you.
I looked over the article and was struck by how confusing this would indeed be to somebody not already intimately familiar with javascript.
Regarding #1, I believe this is a hint to the JIT compiler that "gender" is a string. Javascript JIT compilers like it when object properties stay the same type (in this case, String). It's silly that the article does not describe this, or that this line is there at all. Maybe it's there to demonstrate that you can override prototype properties in a "new Person" instance
Regarding #2, when you call object.method() in automatically calls method where the stack fills in "object" as "this". but if you do something like var detachedmethod = curobject.method and then call detachedmethod(), it does not call with "this" bound as curobject (instead, in the method body, this === undefined. Or maybe "window" I'm not sure :-))
All in all, it's a bunch of nitpicking, and not very important for day to day javascript usage, and can be picked up as you go along.
Here is the correct answer.
1) The prototype definition is not for a default value for Person. In fact, if you create another new Person with no gender, you will see it remains undefined.
var person2 = new Person();
person2.sayGender; // alerts undefined
The point here is to show that the constructor definition overrides a prototype definition.
2) Calling genderTeller() causes undefined because genderTeller is a global function which happens to have same function definition that it copied from person1.sayGender method. genderTeller is same as window.genderTeller.
Therefore when you execute genderTeller(), 'this' = window. Since window does not have a 'gender' property, you get an undefined. You can see it by this code
genderTeller(); // returns undefined
gender = 'hi there';
genderTeller(); // returns 'hi there'
Hope that helps. Here is a Plunker. http://plnkr.co/edit/wwc2vYIvH9QdFYStesVW
I am trying to wrap my head around this idea of 'argument passing.' In a book I am reading it states that arguments are only passed by value not by reference.
function addTen(num) {
num + = 10;
return num;
}
var count = 20;
var result = addTen(count);
alert(count); // 20 - no change
alert(result); // 30
The example above is pretty clear, but the example below leaves me very confused.
When person is passed to the setName function, doesn't it mirror the local variable 'obj'
and flow down the statements in the function?
i.e. person is first set to the property name, then it's assigned to a new Object, and finally this new created person object is assigned the property 'Gregg'????
Why do you get 'Nicholas'!!!!
function setName(obj) {
obj.name = "Nicholas";
obj = new Object();
obj.name = "Greg";
}
var person = new Object();
setName(person);
alert(person.name); //" Nicholas"
Objects are passed to function as a copy of the reference. Now what happens in your example is next:
var person = new Object();
function setName(obj) { // a local obj* is created, it contains a copy of the reference to the original person object
obj.name = "Nicholas"; // creates a new property to the original obj, since obj here has a reference to the original obj
obj = new Object(); // assigns a new object to the local obj, obj is not referring to the original obj anymore
obj.name = "Greg"; // creates a new property to the local obj
}
setName(person);
alert( person.name); //" Nicholas"
* = obj is a local variable containing a value, which is a reference to the original obj. When you later change the value of the local variable, it's not reflecting to the original object.
You get "Nicholas" precisely because JavaScript is never "by reference". If it was, you'd be able to update the person variable from any location. That's not the case, so the new Object() in the function doesn't mutate the outer person variable.
But it's also not the case that variables refer to the objects themselves, but rather variables hold a special type of reference that let you update the object without directly accessing the memory.
That's why although JavaScript is always "by value", you never get a full copy of an object. You're merely getting a copy of that special reference. As a result, you can manipulate the original object passed via the copy of the reference, but you can't actually replace it via the reference.
Everything is pass-by-value in JavaScript. When you pass anything as an argument, JS makes a copy of that and sends it to the function. When an Object is passed, JS copies the reference of that object into another variable and passes that copied variable to the function. Now, since the passed variable is still pointing to the object, you can alter its properties using the . or [] notation. But if you use new to define a new object then that variable just points to the new reference.
function setName(obj) {
obj.name = "Nicholas"; // obj pointing to person reference
obj = new Object(); // obj now pointing to another reference
obj.name = "Greg"; // you have changed the new reference not person reference
}
var person = new Object(); // person pointing to person reference
setName(person);
alert( person.name); //" Nicholas"
Parameters are passed by value, and for objects that means that the value is a copy of the reference to the object.
It's the same thing as when you do a simple assignment, that is also by value:
// a variable that contains a reference to an object:
var person = new Object();
// another variable, that gets a reference to the same object:
var people = person;
// a function call with a reference to the object:
setName(person);
In the function, the parameter is a local variable that works independently of the variable used to send the reference into the function, but it references the same object:
function setName(obj) {
// as the variable references the original object, it changes the object:
obj.name = "Nicholas";
// now the variable gets a reference to a new object
obj = new Object();
// the new object is changed
obj.name = "Greg";
}
Pass by reference means this:
function a(obj) {
obj = 3;
}
var test = new Object();
a(test);
console.log(test); //3, so I have lost the object forever
I.E. even variable assignments will be visible to the caller.
Of course if the target function modifies an object passed to it then those modifications
to the object itself will be visible to the caller.
Does object in javascript pass by reference?
If yes why this code not working.
function change(myObj)
{
myObj={};
myObj.a=2;
}
o={a:1};
change(o);
alert(o.a); //alert 1
but when I do
function change(myObj)
{
myObj.a=2;
}
o={a:1};
change(o);
alert(o.a); //alert 2
I'll explain this thoroughly
o={a:1};
first you set global variable o to be a reference of new anonymous object that have attribute variable a with value = 1 name this object {a:1} as '1A'
change(o);
now you call function change and javascript check of typeof variable o and it's 'object' actually it's should be 'reference that pointed to object' so the reference of object {a:1} is pass into function change by the way if variable is primitive it will pass only by value
function change(myObj){
now function change create variable myObj with typeof 'undefined' by default and then change to 'object' because it got reference parameter and now the variable myObj is a reference variable that pointed to object '1A' => {a:1} and myObj is visible only in function change
and global variable o maybe still point to object '1A' => {a:1} if myObj is just a copy of reference to object '1A' => {a:1} by language design
myObj={};
now the reference variable myObj is point to new anonymous empty object {} name this object as '2B'
myObj.a=2;
}
now you use reference myObj to set object '2B' => {} to have new attribute a with value = 2
and end the scope of function that mean global can't see object '2B' => {a:2}
alert(o.a); //alert 1
variable still point or may be point back to object {a:1} ,reference o can't lose it point, because object '2B' => {a:2} can't be seen outside function change and will be destroyed by garbage collection because it's lost the reference and object '1A' => {a:1} can't be destroyed by garbage collection because variable o still point at it that why you call o you receive object '1A' => {a:1}
sorry for my bad grammar but I try my best to make it easy to read.
The reference to the object is passed to methods. In your first example you are modifying the reference to point to a different object instead of trying to change the object pointed to by the reference and so, the changes are not visible outside that method.
In your second example, you are changing the state of the object pointed to by myobj reference and hence are visible outside the method.
In this case you are overwriting the reference to actual object.
function change(myObj)
{
myObj={}; //overwriting the reference in myObj here.
myObj.a=2;
}
o={a:1};
change(o);
alert(o.a); //alert 1
Think of it this way:
function change(myObj = referenceToObjectPassedIn)
myObj = new Object() ;
// referenceToObjectPassedIn lost in limbo
myObject.a = 2; //modifying newly created object.
To solve your problem you will have to return the new object.
In example 1 you change what myObj references, so you end up changing a different object then the one you intended. When
alert(o.a);
is executed, o.a hasn't been changed since the object declaration, so 1 is returned. I hope that helps a bit. Also read this and it should clear some things up, helped me out when I was first learning JavaScript: http://www.snook.ca/archives/javascript/javascript_pass/.
When i started learning function in C++ its all around pass by value and reference.
Is there something similar we have in javascript ?
If yes/not how it works in case of javascript?
Thanks all.
Other answers to this question are correct - all variables are passed by value in JavaScript, and sometimes that value points to an object.
When a programming language supports passing by reference, it's possible to change where the variable points from inside a function. This is never possible in JavaScript.
For example, consider this code which attempts to reassign the passed variable to a new value:
function changeCaller( x ) {
x = "bar"; // Ha ha!
}
function testChangeCaller() {
var x = "foo";
changeCaller(x);
alert(x); // still "foo"
}
testChangeCaller();
Attempts to point variables at new objects fails in the same way the above example fails to reassign a primitive string:
function changeCaller( x ) {
x = new Object(); // no longer pointing to the same object
x.a = "bar";
}
function testChangeCaller() {
var x = new Object();
x.a = "foo";
changeCaller(x);
alert(x.a); // still "foo"
}
testChangeCaller();
The feature which leads people to believe they're dealing with a pass-by-reference scenario is when modifying objects. You can make changes to an object or array, because the local variable points to the same object:
function changeCaller( x ) {
x.a = "bar";
}
function testChangeCaller() {
var x = new Object();
x.a = "foo";
changeCaller(x);
alert(x.a); // now "bar", since changeCaller worked on the same object
}
testChangeCaller();
Hope this helps!
JavaScript is always pass by value, never pass by reference. A lot of people confuse this because of the way objects work.
There is no "pass by reference" for any variable in JavaScript (no, not even if an object is assigned to that variable). All variables and arguments are assigned by value. If the assigned value is an object, then the value of the new variable is a reference to that object, but assigning a new value/object to the new variable will not affect the original variable.
Some people term this behaviour passing "value by reference".
A comparison - PHP
$foo = "foo";
$bar = &$foo; // assign by reference
$bar = "bar";
echo $foo; // -> output: "bar"
JavaScript
foo = {"foo": true};
bar = foo; // assign value by reference
bar = {"bar": true};
alert(JSON.stringify(foo)); // -> output: '{"foo": true}
Regard the discussion, the considerations about "value" and "reference" are wrong on the exception of the Pointy comment.
Javascript like other reference laguages like c# or java, don't pass a referece to the variable itself to the method, but the reference of the object referenced by the variable.
What the people here is expecting, is passing a pointer to the variable which is referencing the object, pass by pointer is not the same as pass by reference, and sure is not the same as pass by value.
The behavior expected here is pass by pointer.
Pass by reference sends the reference to the object.
Pass by value copy the object stored in the variable and pass the copy
to the method.
The pass by value, pass by reference discussion is an evil meme. This evil meme crops up in Java discussions too.
It's simple: The bit pattern of the value is copied to the parameter. It doesn't matter if the bit pattern is an int or if it's the address of an object -- it's just copied, bit by bit, into the parameter. It couldn't be simpler. The run-time isn't doing something special for primitives versus references. It simply, and always, just makes a copy of the value.
The computer science term for this is "pass by value."
Pass by reference just isn't used in programming any more. In older languages, like Pascal, you could code a function to directly alter the value in the calling routine. So, for example, an int variable in the calling routine could be altered in the called function.
Primitive values are passed via value and objects are passed via reference.
Strings are immutable, so they are passed via reference although they are considered as primitive type.