I just can't understand how variables are passed, why are some passed by reference while other by value?
Example:
var a=4;
var b=a;
b=b++;
alert(a);//unmodified 4
var c=["t","ttt"];
var d=c;
d=d.sort(function(x,y){return (y.length-x.length);});
alert(c);//modified ["ttt","t"]
Where can I find a list of what variables will work like the first example and which like the second? (booleans, strings, etc... there are too many to test them all by miself)
JavaScript is always pass by value.
It's very common to say that objects in JavaScript are pass by reference, however that is not true. In a true pass by reference language, you could pass a reference to an object's reference, and have it point to another object. This is not possible in JavaScript.
Take, for example, C#. By default everything in C# is pass by value, just like JavaScript.
void foo(string s) {
s = "passbyvalue";
}
string a = "original value";
foo(a);
// a is still "original value"
However, if you alter foo to use pass by reference, the behavior changes:
void foo(ref string s) {
s = "passbyreference";
}
string a = "original value";
foo(ref a);
// a is now "passbyreference"
In JavaScript, only the first example is possible.
In JavaScript, everything is pass by value. This includes the object reference (yes, it is confusing). The reference itself is a value (it's very much like a pointer). It merely contains an id that allows the runtime to look up the object that is most likely stored in its heap. When you pass an object to a function, you are actually copying its reference into the function
It may be a seemingly small, and even anal, difference. But it's a key difference. Languages that have true pass by reference such as C# and C++ allow you to do things that are simply not possible in languages like JavaScript. The above trite example is one.
Imagine everything in JavaScript as an object. Object references are copied by value, but object properties are still used by reference. So:
var a = {};
var b = a;
b = 'Blah';
console.log(a); // Still {}
and
var a = {};
var b = a;
b.test = 'Blah';
console.log(a); // Is now {test: 'Blah'}
To simplify things a little: properties are by reference, values are by value.
Usually you can check the method on MDN. For example, the sort method's documentation states (emphasis added):
Sorts the elements of an array in place and returns the array.
The "in place" there says it will modify the array.
All primitives (for example, numbers and booleans) are passed by value; all objects are passed by reference, although some (like String objects) are immutable (although still passed by reference).
All objects get passed by reference and values by value. (technically this is not true, but it explains the behaviour)
Related
Can someone explain to me the difference of when to use a function by feeding your variables into the parenthesis, and when to tack the function on after the variable with a period, like using the toString() function?
example code
function addMe(a){
a = a+1;
return a;
}
var num = 1;
addMe(num);
num.toString();
I'm not actually sure if my syntax is correct, but I want to know when to feed a variable as a parameter, like how I feed the variable num, to the addMe function. And when to use the function .toString() by putting a period after the variable and typing out the function.
could I have done something like this- provided I built my function correctly?
var num = 1;
num.addMe();
Thanks for the help!
The first is used for simple 'stand alone' functions, while the latter is used for object methods. E.g a number object by default has a toString() method. Some object methods may also require parameters to be passed between the parentheses.
Variables (a function declaration is just a function stored in a variable) are looked up in the scope chain (going up to the next outer scope until a variable with the name is found):
let a = 1; // outer scope
{ // inner scope
console.log(a); // looked up in "inner scope", than "outer scope"
}
Properties of an object are looked up in the objects prototype chain, so if you do
a.b
then a gets looked up in the scopes as explained above, then b is accessed on the resulting object (everything is an object in JavaScript, except for "nothing" (undefined, null)) by looking up the prototype chain. For a simple object, the chain is quite short:
const a = { b: 1 }; // object -> Object.prototype
Here b will be found in the object itself. However all objects inherit from the Object.prototype object, so if you add a property to that (please don't):
Object.prototype.test = 1;
you can then look it up on every object, as the lookup traverses up the prototype chain, and reaches Object.prototype:
console.log({}.test); // 1
Now for numbers (like in your case), they inherit the Number.prototype so you could do:
Number.prototype.addMe = function() {
console.log(this);
};
// two dots are needed to distinguish it from numbers with a fraction (e.g. 1.2)
1..addMe();
That said, now addMe can be called on every number, everywhere in your code. While that might seems useful, it is actually a pain as you don't know where a certain method was added
1..whereDoIComeFrom()
that makes code unreadable and unstructured. Instead if you need a certain functionality multiple times, abstract it into a function, don't touch the native prototypes.
I assume that addMe is just a simplified example, if it isn't, read on:
If you pass an argument to a function in JavaScript, the value will be copied (it is a bit more complicated with non primitives (everything except numbers, booleans etc.)) into the parameter variable of the function called so here:
function addMe(a){
a = a+1;
console.log(a); // 2
return a;
}
var num = 1;
addMe(num);
console.log(num); // 1 ... ?
you actually got two variables (a and num), changing a does not change num. But as you return a you can do:
num = addMe(num);
which copies the value of num into a, then increases a by one and then copues the value of a back to num.
When you did var num = 1 you created a JavaScript object. It looks just like a number but you can think of everything in JavaScript as an object (simplification) and all these objects have different features. So a number has some features, a string has some other features, etc.
You mentioned one feature: toString. Another feature would be toLowerCase.
toString and toLowerCase are functions that come with JavaScript. These functions are then "put on" all of these objects for us to use.
I can have a string variable like
var text = 'MY TEXT'
var lowercaseText = text.toLowerCase()
console.log(lowercaseText) // my text
This code will work because it was decided that the toLowerCase function should work on strings
I can also have an array (list of items)
const list = ['A', 'B', 'C']
const answer = list.toLowerCase()
console.log(answer)
But this code won't work because toLowerCase doesn't work on arrays. So you get the following error message: list.toLowerCase is not a function.
Basically its saying: I don't know what toLowerCase means when used on this list variable (array).
In JavaScript this is called prototypes. Prototype is a way for JavaScript to get some feature from another. Basically: I have all kinds of functions, what object can use what functions. This is called the prototype chain.
In both cases you are using a function. addMe is a function you created and toString is a function in JavaScript that has been placed on objects through this prototype-chain.
Im not actually sure if my syntax is correct
Yes your syntax is correct. Your addMe function is the standard way to create a function in JavaScript.
But i want to know when to feed a variable as a parameter, like how i
feed the variable num, to the addMe function.
Just like you did, you define a function and parameters like you did.
..and when to use the function .toString() by putting a period after
the variable and typing out the function.
When you want to place your function on a object so that all instances of that object can you that object.
In most cases, espcially when you are starting out. You don't have to worry about these prototypes. The way you did.
function addMe(number) {
return number+1
}
const answer = addMe(1) //2
Is a standard way of defining a function and calling it.
Arrays are passed by reference in javascript. That means arrays are mutable and can be changed in called function. Why am I not able to Re-initialization an array in called function?
This is also true for python
function calling(){
var arr = [1,2]
console.log(arr); //prints [1,2]
called(arr);
console.log(arr); //prints [1,2,3,4],but I was expecting [5,6]
}
function called(arr){
arr.push(3)
arr.push(4)
arr = [5,6]
}
calling()
UPDATE
I am seeking justification of (mutability, pass by reference, pass by assignment and re-initialization of an array)
Please don't post workaround and solution of the problem. I know how to get arr to print [5,6]
Arrays are passed by reference in javascript.
No, they aren't. ECMAScript/JavaScript is strictly pass-by-value. (More precisely, call-by-sharing, which is a special case of pass-by-value.)
That means arrays are mutable and can be changed in called function.
No, that's not what it means. It means exactly what it says: that the reference within the caller's scope to the array is passed as an argument into the function, and not the value.
Whether or not the array is mutable or not has nothing to with pass-by-reference vs. pass-by-value. ECMAScript is not a purely functional language, most objects can be mutated. Numbers, Symbols, and Strings are an exception.
Why am I not able to Re-initialization an array in called function?
You are trying to modify the reference within the caller's scope. That only works with pass-by-reference. ECMAScript is not pass-by-reference, whoever told you that is simply wrong.
This is also true for python
Python behaves identically to ECMAScript in this regard, yes, it is also pass-by-value.
Your confusion stems from the fact that you erroneously believe ECMAScript/JavaScript is pass-by-reference, when in fact it is not.
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, for reference types it is call-by-object-sharing, which is a special case of pass-by-value!');
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, for reference types it is call-by-object-sharing, which is a special case of pass-by-value!
def is_python_pass_by_value(foo):
foo[0] = 'More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value!'
foo = ['Python is not pass-by-reference.']
quux = ['Yes, of course, Python *is* pass-by-value!']
is_python_pass_by_value(quux)
print(quux[0])
# More precisely, for reference types it is call-by-object-sharing, which is a special case of pass-by-value!
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.)
// In C#, struct defines a value type, class defines a reference type
struct MutableCell
{
public string value;
}
class Program
{
// the ref keyword means pass-by-reference, otherwise it's pass-by-value
// You must explicitly request pass-by-reference both at the definition and the call
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." };
// the first two are passed by value, the other two 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.
}
}
If you want to get technical, Javascript is really only "pass by value" - it is not "pass by reference". When you pass an object (like an Array), you are passing by value and the value is a reference (a copy of a reference to the array, not a copy of the actual array). This means you can use the value reference to mutate the original object, but it's not an actual reference to the original variable so you can't affect the contents of the original variable itself (e.g. you can't cause that other variable to point at a new object).
Since this language jargon doesn't actually explain what is going on for many folks, what follows here is more of a description of how it works:
When you do:
arr = [5,6]
inside your function, you are just assigning a new array to the arr function argument. You've just instructed Javascript to take the arr argument variable and point it at a new array object. That has no effect at all on the original array object that was passed into the function. It still happily exists in its other life.
You could change that array like this:
function called(arr){
arr.push(3)
arr.push(4)
// now set arr back to [5,6]
arr[0] = 5;
arr[1] = 6;
arr.length = 2;
}
It's a bit of a misnomer to say arrays are passed by reference because it isn't really a full reference like you would find in C++, for example. Some people say it's "pass by sharing" or "pass by pointer". Some people even call it "pass by value, but the value is a reference" which is probably technically correct, but doesn't usually help newbies understand what is going on. In my brain (partly because I know C/C++), I think of it like "pass by pointer".
Though Javascript doesn't actually have it's own data type that is a pointer, passing an array works more like passing a pointer works in C++. If you index off the pointer, you are accessing the original object:
arr[0] = 5; // this changes the original object
But, if you reassign the pointer a new value:
arr = [5,6]; // this just makes arr point at a new and different array
Then, you are just making the pointer variable itself point at a new object and the original object still remains untouched.
So, in summary. If you reference arr as in arr.push(x), then you are mutating the original array object.
But, if you assign arr a new array as in arr = [5,6], then you are just telling Javascript that you want the arr variable to point at a new array. Your arr variable in that function now points at a different array than it did before. The original array can no longer be reached by this code. But any other code that was pointing at that original array is still pointing at that original array. If you know C/C++, it actually works fairly similarly to a pointer in C++.
Here's a simpler example that is outside of the context of a function argument:
var x = [1,2];
var y = x;
console.log(x); // [1,2]
console.log(y); // [1,2]
y = [3,4];
console.log(x); // [1,2]
console.log(y); // [3,4]
You've merely asked y to now point to a new array [3,4]. Assigning y to point to a new array does not affect the original array at all.
In this example, the variable y is like the arr function argument in your called() function. Assigning a new value to it doesn't change the original in any way.
In Python:
In [170]: def called(arr):
.....: arr.append(3)
.....: arr.append(4)
.....: arr=[5,6]
.....:
In [171]: arr=[1,2]
In [172]: called(arr)
In [173]: arr
Out[173]: [1, 2, 3, 4]
Initially in called, arr is a reference to the mutable list [1,2]. The 2 append calls modify that list. But the arr=[5,6] step reassigns the variable. The link to outside arr is broken, so there's no further change.
If I'd added a return arr statement to the call,
In [175]: called(arr)
Out[175]: [5, 6]
In [176]: arr
Out[176]: [1, 2, 3, 4, 3, 4]
I modify the global arr again, but return the [5,6].
called would be clearer if written:
def called(arr):
arr.append(3)
arr.append(4)
res=[5,6]
return res
The last 2 lines have nothing to do with initial arr argument, so there is not point in reusing the variable name.
For further illustration of what is going on, look at the object id at various points:
In [178]: def called(arr):
arr.append(3)
arr.append(4)
print(id(arr))
arr = [5,6]
.....: return arr
.....:
In [179]: id(arr)
Out[179]: 2999818796
In [180]: id(called(arr))
2999818796 # id of global arr
Out[180]: 2999999564 # id of returned list
In [181]: id(arr)
Out[181]: 2999818796
What is the difference between a JS:
Object, Property and Variable ?
Sorry I'm new to JavaScript but from the way I'm understanding it is a Variable is a container to store information/data types yes ?
An object is a variable but with several different properties (whereas with a variable you have one property)? name:value pairs
a property is the building blocks of objects? is that what makes an Object an Object? because it is a variable with several name:value pairs? ........
I'm supper confused!!! are all three the same are they like interchangeable?
the only example I can think of is
Human body:
Cells
Tissues
Organs
-organs are made up of tissues
-tissues are made up of cells
-cells are tissues, basically lots of cells make up tissues and lots of tissues make up organs.
So basically organs are also cells but they are made up of a lot of cells?
I'm a bit dumb and slow when it comes to learning can somebody please enlighten me?
Explain the differences between them in very simple basic language like your explaining it to a 10 year old or something please
answers much appreciated,
Thanks :)
ps There may be a part 2 to this question
the way I'm understanding it is a Variable is a container to store information/data types yes ?
Almost. A variable is a container that stores a value. Each value is of a specific data type. Common types are number, string and Boolean.
Example:
var userID = 42;
userID is a variable. It contains the value 42. 42 is a number value, i.e. it is of type number.
A JavaScript object is a value of type object. Objects are not just simple, scalar values, they are "container" values. They can themselves contain multiple different values.
Essentially objects are key-value stores, i.e. they contain one or more keys associated with a value. These key-value pairs are called properties.
Example:
var record = {
name: 'Paul',
age: 42
};
record is a variable. It contains an object as value. The object has two properties, name and age. name holds a string value, age a number value.
When one refers to 'variable' one typically imagine a container with some memory to hold a value.
Objects are variables too but dynamically transform to containers of primitives or more-complex values upon Assignment! Complex values can be objects that hold primitive data types or even other objects such in the example below :
var SNOCounter; //gives undefined ^
SNOCounter = 3;
AccObjVar = {firstName:"John", lastName:"Smith"}; //creates an JS "object" variable with two "properties" that hold 'string' type values
AccountWrapperObj = {SNO:SNOCounter,AccountName:AccObjVar};
The dynamism of object properties is such that although AccountWrapperObj which is a JS Object holds a primitive value and Object as its original value. Replacing the AccountName property with an integer can be done by just assigning it the integer value (the properties have dynamic data types just like variables in Javascript)
AccountWrapperObj.AccountName= 'Albert Einstein'; // changes the type of AccountName from AccObjVar object type to a String
----------Extra Info ---------------
^ I am not quite clear on the memory assignment part at this stage. Link says there needs to be a bare minimum memory here for referencing the variable and actually assigning it a value.
Does declaring a variable in JavaScript with var without assignment consume memory?
A variable is a binding to a value in memory and not an object.
The item in a box analogy isn’t quite right. I think that it’s more along the lines of two tin cans connected by a string, one can being the reference(variable) and the other being the value.
I'm also new to JS, so I'll tell what's helping me here
one thing that's helping me is to think about variables as 'labels', something temporary related to execution (a metaphor from Luciano Ramalho's Fluent Python book...), and not as 'boxes', a metaphor that I've seen in a lot of tutorials
so variables are temporary, and related to execution of some function, or of the whole script (depending of where they're declared... see the difference of var, let and const for more about this)
properties, on the other hand, are related to objects, attached to the obj while it or the property exists; so you cannot create a property that's not related to an obj
let myObj = {}; // 'myObj' is the 'label' of the obj we're creating
myObj.prop = true; // we create 'prop', a property of 'myObj', using the dot notation
almost everything in JS is an obj, and objs are custom types/structures for data; functions are also objects, but they're a 'special' kind of obj, we can create and return objects with them (we can execute functions to create/return objs); so
let foo; // declaring an empty variable; the word let is related to the scope of the variable, you can use var, let or const when declaring variables
foo = function(){ return {}; }; // foo returns an empty obj
myObj = foo(); // we execute foo() so that myObj is again an empty obj
the value of a property can also be an object, so we can also do
myObj.foo = function(...args){ // receives no or more arguments
const createProps = (el, i) => { // declares a variable and defines an arrow function
this[`prop${i+1}`] = el; // uses the index of the argument to create the name of the property, with the argument value
}
args.forEach(createProps); // for each arg, create a property
}
myObj.foo('some', 'new', 'properties'); // execute the function, creating new properties in 'myObj'
above, the function that creates properties for my myObj is part of myObj, as a property...
so objects and properties have to do with data structuring, how I relate the different kinds of data in my code; and functions and variables - these 'temporary labels' - have to do with execution, doin' stuff, creating objs, and so on... both 'portions' workin' together, of course
I was trying to understand some javascript and found some quite unexpected behavior. Not knowing much about this language I wanted to find out what this behavior is called so that I can read about it formally.
Here's an example of the behavior:
var test={'x':2};
var test2=test;
test2.sourceLinks = [];
console.log('test',test);
console.log('test2',test2);
To my amazement, I found that modifying the 2nd variable somehow modifies the first as well. The variable "test" will also have an attribute .sourceLinks = []. Do I understand what's happening correctly, and if so, what's the formal term for this behavior?
I found that the answer to this is covered in How do I correctly clone a JavaScript object? after I posted it, although that covered more than I was asking about.
Behavior is called creating a reference. When variable assigned is an object actually it is not copied, rather the result of assignment is a new reference (pointer) to the object.
This doesn't happen with primitive types:
number,
string,
boolean,
null,
undefined.
But happens with all object types:
object,
Array,
function.
This difference is significant in javascript. When some value should be passed to another scope and it might be modified there it should be passed be reference.
function main(){
var x = 1;
modify(x);
console.log(x);//x remains 1
}
function modify(arg){
arg = 10;
}
Whereas when it is passed as a field of an object, it can be modified via reference to an object:
function main(){
var o = {x : 1};
modifyObj(o);
console.log(o);//o.x now equals 10
}
function modifyObj(arg){
arg.x = 10;
}
It's holding the reference.
When you assign object/array/function to another object/array/function it'll assign reference instead of value.
To overcome this you have to clone it
When declaring a variable in Javascript you are creating an object in memory and the variable in the scope is a pointer to that memory object.
In your example both variables (test and test2) are pointing to the same object. Hence, when you modify the the either variable pointer, it is modifying the same object in memory.
I want to pass a value to a Change function. But i want to pass only the reference inside the array. This works:
var test = ["Hello World","Hello You"];
HelloCar(test,0);
function HelloCar(myarray,key)
{
myarray[key] = "Hello Car";
}
But this will fail:
var test = ["Hello World","Hello You"];
HelloCar(test[0]);
function HelloCar(myvalue)
{
myvalue = "Hello Car";
}
Is there a way to pass only the real reference, without the complete data?
How about using a prototype:
Array.prototype.HelloCar= function ( idx ) {
this[idx] = 'Hello Car'
}
test.helloCar(0)
Primitive types (such as Strings, Numbers and Booleans) are always passed as values, not references.
The closest you will get to emulating referencing variables is by wrapping them in an Object.
However, it might be comforting for you to know that you'll be able to achieve whatever you need to do without trying to bend JavaScript syntax to your will.
If you're anxious about a method having access to data it shouldn't (not that I can see any reason for this, in your instance), then I would write it like this:
var test = ["Hello World","Hello You"];
test[0] = HelloCar(test[0]);
function HelloCar(string){
// any logic to change string in any way
string = "HelloCar";
return string;
}
This may seem a bit pointless, but let's pretend (for argument's sake) that you could pass a reference to a variable of a primitive type... If so, the only information the method would have access to would be it's value, because there is little more to a string variable than a memory address and a value. Being a string, it doesn't have a great deal of information, other than a bunch of characters. Ergo, any logic we need to apply to the variable in the way of contorting its value is actually going to be based on the same principals as the method above.