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.
Related
I'm following some canvas tutorial. The code below is a snippet of that.
In this snippet, why would they not choose for runAnimation to be a simple boolean? I would think the x = !x statement would work anyways, but when i tried changing the code to use booleans, the code didn't work.
So, what's the difference between a boolean as primitive and a boolean as property of an object?
/*
* define the runAnimation boolean as an object
* so that it can be modified by reference
*/
var runAnimation = {
value: false
};
// add click listener to canvas
document.getElementById('myCanvas').addEventListener('click', function() {
// flip flag
runAnimation.value = !runAnimation.value;
All arguments are passed by "value" in JavaScript. This means that when an argument is passed, a copy of what's stored in the variable is passed.
Primitives (like booleans) store the actual data they represent and so, when a primitive is passed, a copy of the data is sent, resulting in two copies of the data. Changes to one, won't affect the other.
But, when you assign an object to a variable, the variable stores the memory location for where that object can be found, not the object itself. Passing an object as an argument results in a copy of the memory address being passed. In these cases, you may wind up with two variables that store the same memory address, so no matter which variable you use, the same one underlying object is affected.
In your scenario, you could certainly make it work with just a boolean variable, but it appears that the tutorial wants to encapsulate that into an object so that copies of the boolean data won't be floating around and there will be less chances of accidentally changing one variable but not another.
Here's some basic examples:
// This function takes a single argument, which it calls "input"
// This argument will be scoped to the function.
function foo(input){
// The function is going to alter the parameter it received
input = input + 77;
console.log(input);
}
var input = 100; // Here's a higher scoped variable also called "input"
foo(input); // We'll pass the higher scoped variable to the function
// Now, has the higher level scoped "input" been changed by the function?
console.log(input); // 100 <-- No, it hasn't because primitives pass a copy of their data
// ************************************************
// Now, we'll do roughly the same thing, but with objects, not primitives
function foo2(obj){
obj.someProp = 100;
console.log(obj.someProp);
}
var obj = {
someProp : 50
};
foo2(obj);
// Here, we see that the original object has been changed by the funciton we passed it to
console.log(obj.someProp);
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.
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 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)
I'm coming to javascript from C background. In javascript, when I use the assignment operator to assign one object to another, does it copy the values from one to the another, or do they both now point to the same data?. Or does the assignment operator do anything in this case?
function point_type()
{
this.x = 0;
this.y = 0;
}
var pnt1 = new point_type();
var pnt2 = new point_type();
pnt1.x = 4;
pnt1.y = 5;
pnt2 = pnt1;
pnt1.x = 8;
pnt2.y = 9;
In the example above, does pnt2.x now equal 8, or does it still equal 4, or does it still equal 0?
Yes, I realize I can test this myself, and I will be doing that while I wait for the community to come up with an answer. However, I'm hoping the answer to my question will go one step past just answering this one example and might shine some light on how javascript objects work and some best practices.
Follow up question:
The answer seems to be that the reference is copied. pnt2 and pnt1 now point to the same data. Is it possible to set up my object so that the values are copied? How is this usually accomplished in javascript? Clearly I don't want to set each attribute individually every time I need to copy this object.
Whenever I need to copy one object to another in JS, I just cast it to a primitive:
var newObject = JSON.stringify(oldObject);
Then when I need to use it:
var evenNewerObj = JSON.parse(newObject);
Hope this helps someone.
In JavaScript, primitive types are copied by value and reference types are copied by reference. More info here: http://docstore.mik.ua/orelly/web/jscript/ch09_03.html
It equals 8.
pnt2 = pnt1
That statement is pointing the pnt2 object to the pnt1 object so any modification you do to pnt1 will show up in pnt2.
Given the object you showed in your example, it is setting a reference to the object. If it were a primitive type (number, date) then it would copy the object.