Related
The WeakSet is supposed to store elements by weak reference. That is, if an object is not referenced by anything else, it should be cleaned from the WeakSet.
I have written the following test:
var weakset = new WeakSet(),
numbers = [1, 2, 3];
weakset.add(numbers);
weakset.add({name: "Charlie"});
console.log(weakset);
numbers = undefined;
console.log(weakset);
Even though my [1, 2, 3] array is not referenced by anything, it's not being removed from the WeakSet. The console prints:
WeakSet {[1, 2, 3], Object {name: "Charlie"}}
WeakSet {[1, 2, 3], Object {name: "Charlie"}}
Why is that?
Plus, I have one more question. What is the point of adding objects to WeakSets directly, like this:
weakset.add({name: "Charlie"});
Are those Traceur's glitches or am I missing something?
And finally, what is the practical use of WeakSet if we cannot even iterate through it nor get the current size?
it's not being removed from the WeakSet. Why is that?
Most likely because the garbage collector has not yet run. However, you say you are using Traceur, so it just might be that they're not properly supported. I wonder how the console can show the contents of a WeakSet anyway.
What is the point of adding objects to WeakSets directly?
There is absolutely no point of adding object literals to WeakSets.
What is the practical use of WeakSet if we cannot even iterate through it nor get the current size?
All you can get is one bit of information: Is the object (or generically, value) contained in the set?
This can be useful in situations where you want to "tag" objects without actually mutating them (setting a property on them). Lots of algorithms contain some sort of "if x was already seen" condition (a JSON.stringify cycle detection might be a good example), and when you work with user-provided values the use of a Set/WeakSet would be advisable. The advantage of a WeakSet here is that its contents can be garbage-collected while your algorithm is still running, so it helps to reduce memory consumption (or even prevents leaks) when you are dealing with lots of data that is lazily (possibly even asynchronously) produced.
This is a really hard question. To be completely honest I had no idea in the context of JavaScript so I asked in esdiscuss and got a convincing answer from Domenic.
WeakSets are useful for security and validation reasons. If you want to be able to isolate a piece of JavaScript. They allow you to tag an object to indicate it belongs to a special set of object.
Let's say I have a class ApiRequest:
class ApiRequest {
constructor() {
// bring object to a consistent state, use platform code you have no direct access to
}
makeRequest() {
// do work
}
}
Now, I'm writing a JavaScript platform - my platform allows you to run JavaScript to make calls - to make those calls you need a ApiRequest - I only want you to make ApiRequests with the objects I give you so you can't bypass any constraints I have in place.
However, at the moment nothing is stopping you from doing:
ApiRequest.prototype.makeRequest.call(null, args); // make request as function
Object.create(ApiRequest.prototype).makeRequest(); // no initialization
function Foo(){}; Foo.prototype = ApiRequest.prototype; new Foo().makeRequest(); // no super
And so on, note that you can't keep a normal list or array of ApiRequest objects since that would prevent them from being garbage collected. Other than a closure, anything can be achieved with public methods like Object.getOwnPropertyNames or Object.getOwnSymbols. So you one up me and do:
const requests = new WeakSet();
class ApiRequest {
constructor() {
requests.add(this);
}
makeRequest() {
if(!request.has(this)) throw new Error("Invalid access");
// do work
}
}
Now, no matter what I do - I must hold a valid ApiRequest object to call the makeRequest method on it. This is impossible without a WeakMap/WeakSet.
So in short - WeakMaps are useful for writing platforms in JavaScript. Normally this sort of validation is done on the C++ side but adding these features will enable moving and making things in JavaScript.
(Of course, everything a WeakSet does a WeakMap that maps values to true can also do, but that's true for any map/set construct)
(Like Bergi's answer suggests, there is never a reason to add an object literal directly to a WeakMap or a WeakSet)
By definition, WeakSet has only three key functionalities
Weakly link an object into the set
Remove a link to an object from the set
Check if an object has already been linked to the set
Sounds more pretty familiar?
In some application, developers may need to implement a quick way to iterate through a series of data which is polluted by lots and lots of redundancy but you want to pick only ones which have not been processed before (unique). WeakSet could help you. See an example below:
var processedBag = new WeakSet();
var nextObject = getNext();
while (nextObject !== null){
// Check if already processed this similar object?
if (!processedBag.has(nextObject)){
// If not, process it and memorize
process(nextObject);
processedBag.add(nextObject);
}
nextObject = getNext();
}
One of the best data structure for application above is Bloom filter which is very good for a massive data size. However, you can apply the use of WeakSet for this purpose as well.
A "weak" set or map is useful when you need to keep an arbitrary collection of things but you don't want their presence in the collection from preventing those things from being garbage-collected if memory gets tight. (If garbage collection does occur, the "reaped" objects will silently disappear from the collection, so you can actually tell if they're gone.)
They are excellent, for example, for use as a look-aside cache: "have I already retrieved this record, recently?" Each time you retrieve something, put it into the map, knowing that the JavaScript garbage collector will be the one responsible for "trimming the list" for you, and that it will automatically do so in response to prevailing memory conditions (which you can't reasonably anticipate).
The only drawback is that these types are not "enumerable." You can't iterate over a list of entries – probably because this would likely "touch" those entries and so defeat the purpose. But, that's a small price to pay (and you could, if need be, "code around it").
WeakSet is a simplification of WeakMap for where your value is always going to be boolean true. It allows you to tag JavaScript objects so to only do something with them once or to maintain their state in respect to a certain process. In theory as it doesn't need to hold a value it should use a little less memory and perform slightly faster than WeakMap.
var [touch, untouch] = (() => {
var seen = new WeakSet();
return [
value => seen.has(value)) || (seen.add(value), !1),
value => !seen.has(value) || (seen.delete(value), !1)
];
})();
function convert(object) {
if(touch(object)) return;
extend(object, yunoprototype); // Made up.
};
function unconvert(object) {
if(untouch(object)) return;
del_props(object, Object.keys(yunoprototype)); // Never do this IRL.
};
Your console was probably incorrectly showing the contents due to the fact that the garbage collection did not take place yet. Therefore since the object wasn't garbage collected it would show the object still in weakset.
If you really want to see if a weakset still has a reference to a certain object then use the WeakSet.prototype.has() method. This method, as the name implies returns a boolean indicating wether the object still exists in the weakset.
Example:
var weakset = new WeakSet(),
numbers = [1, 2, 3];
weakset.add(numbers);
weakset.add({name: "Charlie"});
console.log(weakset.has(numbers));
numbers = undefined;
console.log(weakset.has(numbers));
Let me answer the first part, and try to avoid confusing you further.
The garbage collection of dereferenced objects is not observable! It would be a paradox, because you need an object reference to check if it exists in a map. But don't trust me on this, trust Kyle Simpson:
https://github.com/getify/You-Dont-Know-JS/blob/1st-ed/es6%20%26%20beyond/ch5.md#weakmaps
The problem with a lot of explanations I see here, is that they re-reference a variable to another object, or assign it a primitive value, and then check if the WeakMap contains that object or value as a key. Of course it doesn't! It never had that object/value as a key!
So the final piece to this puzzle: why does inspecting the WeakMap in a console still show all those objects there, even after you've removed all of your references to those objects? Because the console itself keeps persistent references to those Objects, for the purpose of being able to list all the keys in the WeakMap, because that is something that the WeakMap itself cannot do.
While I'm searching about use cases of Weakset I found these points:
"The WeakSet is weak, meaning references to objects in a WeakSet are held weakly.
If no other references to an object stored in the WeakSet exist, those objects can be garbage collected."
##################################
They are black boxes: we only get any data out of a WeakSet if we have both the WeakSet and a value.
##################################
Use Cases:
1 - to avoid bugs
2 - it can be very useful in general to avoid any object to be visited/setup twice
Refrence: https://esdiscuss.org/topic/actual-weakset-use-cases
3 - The contents of a WeakSet can be garbage collected.
4 - Possibility of lowering memory utilization.
Refrence: https://www.geeksforgeeks.org/what-is-the-use-of-a-weakset-object-in-javascript/
##################################
Example on Weakset: https://exploringjs.com/impatient-js/ch_weaksets.html
I Advice you to learn more about weak concept in JS: https://blog.logrocket.com/weakmap-weakset-understanding-javascript-weak-references/
I read a book called "Professional Javascript for web developer" and it says: "Variable is assigned by Reference value or Primitive Value. Reference values are objects stored in memory". And then it says nothing about how Primitive value is stored. So I guess it isn't stored in memory. Based on that, when I have a script like this:
var foo = 123;
How does Javascript remember the foo variable for later use?
Okay, imagine your variable to be a piece of paper - a sticky note.
Note 1: A variable is a sticky note.
Now, a sticky note is very small. You can only write a little bit of information on it. If you want to write more information you need more sticky notes, but that's not a problem. Imagine you have an endless supply of sticky notes.
Note 2: You have an endless supply of sticky notes, which store small amounts of information.
Great, what can you write on your sticky note? I can write:
Yes or no (a boolean).
My age (a number).
My name (a string).
Nothing at all (undefined).
A doodle or anything else which means nothing to me at all (null).
So we can write simple things (let's be condescending and call them primitive things) on our sticky notes.
Note 3: You can write primitive things on your sticky notes.
So say I write 30 on a sticky note to remind myself to buy 30 slices of cheese for the little party I'm throwing at my place tonight (I have very few friends).
When I go to put my sticky note on the fridge I see that my wife has put another sticky note on the fridge which also says 30 (to remind me that her birthday is on the 30th of this month).
Q: Do both the sticky notes convey the same information?
A: Yes, they both say 30. We don't know if it's 30 slices of cheese or the 30th day of the month, and frankly, we don't care. For a person who didn't know any better, it's all the same.
var slicesOfCheese = 30;
var wifesBirthdate = 30;
alert(slicesOfCheese === wifesBirthdate); // true
Note 4: Two sticky notes which have the same thing written on them convey the same information, even though they are two different sticky notes.
I'm really excited about tonight - hanging out with old friends, having a great time. Then some of my friends call me and say that they won't be able to make it to the party.
So I go to my fridge and erase the 30 on my sticky note (not my wife's sticky note - that would make her very angry) and make it a 20.
Note 5: You can erase what's written on a sticky note and write something else.
Q: That's all good and fine, but what if my wife wanted to make write a list of groceries for me to pick up while I was out to get some cheese. Would she need to write a sticky note for every item?
A: No, she would take a long list of paper and write the list of groceries on that paper. Then she would write a sticky note telling me where to find the list of groceries.
So what's happening here?
A list of groceries is obviously not simple (erm... primitive) data.
My wife wrote it on a longer piece of paper.
She wrote where to find it in a sticky note.
Honey, the list of groceries is under your keyboard.
To recap:
The actual object (the list of groceries) is under my keyboard.
The sticky note tells me where to find it (the address of the object).
Note 6: Reference values are references to objects (addresses where they will be found).
Q: How do we know when two sticky notes say the same thing? Say my wife made another grocery list in case I misplaced the first, and wrote another sticky note for it. Both the lists say the same thing, but do the sticky notes say the same thing?
A: No. The first sticky note tells us where to find the first list. The second one tells us where to find the second list. It doesn't matter whether the two lists say the same thing. They are two different lists.
var groceryList1 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
var groceryList2 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
alert(groceryList1 === groceryList2); // false
Note 7: Two sticky notes convey the same information only if they refer to the same object.
This means if my wife made two sticky notes reminding me where the grocery list is, then the two sticky notes contain the same information. So this:
Honey, the list of groceries is under your keyboard.
Contains the same information as:
Don't forget that the list of groceries is under your keyboard.
In programming terms:
var groceryList1 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
var groceryList2 = groceryList1;
alert(groceryList1 === groceryList2); // true
So that's all that you need to know about primitives and references in JavaScript. No need to get into things like heap and dynamic memory allocation. That's important if you're programming in C/C++.
Edit 1: Oh, and the important thing is that when you pass variables around you're essentially passing primitive values by value and reference values by reference.
This is just an elaborate way of saying that you're copying everything written on one sticky note to another (it doesn't matter whether you're copying a primitive value or a reference).
When copying references, the object being referenced doesn't move (e.g. my wife's grocery list will always stay under my keyboard, but I can take the sticky note I copied anywhere I want - the original sticky note will still be on the fridge).
Edit 2: In response to the comment posted by #LacViet:
Well for starters we're talking about JavaScript, and JavaScript doesn't have a stack or a heap. It's a dynamic language and all the variables in JavaScript are dynamic. To explain the difference I'll compare it to C.
Consider the following C program:
#include <stdio.h>
int main() {
int a = 10;
int b = 20;
int c = a + b;
printf("%d", c);
return 0;
}
When we compile this program we get an executable file. The executable file is divided into multiple segments (or sections). These segments include the stack segment, the code segment, the data segment, the extra segment, etc.
The stack segment is used to store the state of the program when a function or interrupt handler is called. For example, when function f calls function g then the state of function f (all the values in the registers at that time) are saved in a stack. When g returns control to f then these values are restored.
The code segment holds the actual code to be executed by the processor. It contains a bunch of instructions the processor must execute like add eax, ebx (where add is the opcode, and eax & ebx are arguments). This instruction adds the contents of registers eax and ebx and stores the result in the register eax.
The data segment is used to reserve space for variables. For example, in the above program, we need to reserve space for the integers a, b and c. In addition, we also need to reserve space for the string constant "%d". Variables reserved thus have a fixed address in memory (after linking and loading).
In addition to all of these, you're also give a little bit of extra space by the Operating System. This is called the heap. Any extra memory you need is allocated from this space. Memory allocated in this way is called dynamic memory.
Let's see a program with dynamic memory:
#include <stdio.h>
#include <malloc.h>
int main() {
int * a = malloc(3 * sizeof(int));
a[0] = 3;
a[1] = 5;
a[2] = 7;
printf("a: %d\nb: %d\nc: %d\n", a[0], a[1], a[2]);
return 0;
}
Because we want to allocate memory dynamically we need to use pointers. This is because we want to use the same variable to point to an arbitrary memory location (not necessarily the same memory location every time).
So we create an int pointer (int *) called a. The space for a is allocated from the data segment (i.e. it's not dynamic). Then we call malloc to allocate the contiguous space for 3 integers from the heap. The memory address of the first int is returned and stored in the pointer a.
Q: What did we learn?
A: A fixed amount of space is allocated for all variables. Each variable has a fixed address. We may also allocate extra memory from the heap and store the address of this extra memory in a pointer. This is called a dynamic memory scheme.
Conceptually this is similar to what I explained about variables being sticky notes. All variables (including pointers are sticky notes). However, pointers are special because they reference a memory location (which is like referencing an object in JavaScript).
However, this is where the similarities end. Here are the differences:
In C everything is passed by value (including addresses in pointers). To pass a reference you need to use indirection via pointers. JavaScript only passes primitives by value. Passing references is handled transparently by the engine and is just like passing any other variable.
In C you can create a pointer to a primitive data type like int. In JavaScript, you cannot create a reference to a primitive value like number. All primitives are always stored by value.
In C you may perform various operations on pointers. This is called pointer arithmetic. JavaScript doesn't have pointers. It only has references. Thus you can't perform any pointer arithmetic.
Besides these three the biggest difference between C and JavaScript is that all variables in JavaScript actually pointers. Because JavaScript is a dynamic language the same variable may be used to store a number and a string at different points of time.
JavaScript is an interpreted language, and the interpreter is usually written in C++. Thus all variables in JavaScript are mapped to objects in the host language (even primitives).
When we declare a variable in JavaScript the interpreter creates a new generic variable for it. Then when we assign it a value (be it a primitive or a reference) the interpreter simply assigns a new object to it. Internally it knows which objects are primitive and which are actually objects.
Conceptually it's like doing something like this:
JSGenericObject ten = new JSNumber(10); // var ten = 10;
Q: What does this mean?
A: It means that all the values (primitives and objects) in JavaScript are allocated from the heap. Even the variables themselves are allocated from the heap. It's wrong to state that primitives are allocated from the stack and only objects are allocated from the heap. This is the biggest difference between C and JavaScript.
A variable can hold one of two value types: primitive values or reference values.
Primitive values are data that are stored on the stack.
Primitive value is stored directly in the location that the variable accesses.
Reference values are objects that are stored in the heap.
Reference value stored in the variable location is a pointer to a location in memory where the object is stored.
Primitive types include Undefined, Null, Boolean, Number, or String.
The Basics:
Objects are aggregations of properties. A property can reference an object or a primitive. Primitives are values, they have no properties.
Updated:
JavaScript has 6 primitive data types: String, Number, Boolean, Null, Undefined, Symbol (new in ES6). With the exception of null and undefined, all primitives values have object equivalents which wrap around the primitive values, e.g. a String object wraps around a string primitive. All primitives are immutable.
In javascript the Primitive values are data that are stored on the stack.
Primitive value is stored directly in the location that the variable accesses.
And the Reference values are objects that are stored in the heap.
Reference value stored in the variable location is a pointer to a location in memory where the object is stored.
JavaScript supports five primitive data types: number, string, Boolean, undefined, and null.
These types are referred to as primitive types because they are the basic building blocks from which more complex types can be built.
Of the five, only number, string, and Boolean are real data types in the sense of actually storing data.
Undefined and null are types that arise under special circumstances. The primitive type has a fixed size in memory.
For example, a number occupies eight bytes of memory, and a boolean value can be represented with only one bit.
And the Reference types can be of any length -- they do not have a fixed size.
A primitive type has a fixed size in memory. For example, a number occupies eight bytes of memory, and a boolean value can be represented with only one bit. The number type is the largest of the primitive types. If each JavaScript variable reserves eight bytes of memory, the variable can directly hold any primitive value.
This is an oversimplification and is not intended as a description of an actual JavaScript implementation.
Reference types are another matter, however. Objects, for example, can be of any length -- they do not have a fixed size. The same is true of arrays: an array can have any number of elements. Similarly, a function can contain any amount of JavaScript code. Since these types do not have a fixed size, their values cannot be stored directly in the eight bytes of memory associated with each variable. Instead, the variable stores a reference to the value. Typically, this reference is some form of pointer or memory address. It is not the data value itself, but it tells the variable where to look to find the value.
The distinction between primitive and reference types is an important one, as they behave differently. Consider the following code that uses numbers (a primitive type):
var a = 3.14; // Declare and initialize a variable
var b = a; // Copy the variable's value to a new variable
a = 4; // Modify the value of the original variable
alert(b) // Displays 3.14; the copy has not changed
There is nothing surprising about this code. Now consider what happens if we change the code slightly so that it uses arrays (a reference type) instead of numbers:
var a = [1,2,3]; // Initialize a variable to refer to an array
var b = a; // Copy that reference into a new variable
a[0] = 99; // Modify the array using the original reference
alert(b); // Display the changed array [99,2,3] using the new reference
If this result does not seem surprising to you, you're already well familiar with the distinction between primitive and reference types. If it does seem surprising, take a closer look at the second line. Note that it is the reference to the array value, not the array itself, that is being assigned in this statement. After that second line of code, we still have only one array object; we just happen to have two references to it.
As already mentioned in the accepted answer and the highest voted answer, primitive values are data that are stored in stack and reference values are object that are stored in heap.
But what does this actually mean? How do they perform differently in your codes?
Primitive values are accessed by value. So when you assign an variable (var a) that has a primitive value to another variable (var b), the value of the variable (a) gets copied into the new variable (b). And when you change the value of the new variable (b), the value of the original variable remain unchanged.
When you assign a variable (var x) that has a reference value to another variable (var y), the value stored in the variable (x) is also copied into the new variable (y). The difference is that the values stored in both variables now are the reference of the actual object stored in the heap. This means that, both x and y are pointing to the same object. So when you change the value of the new variable (y), the value of the original valuable (x) is also changed (because the actual object in the heap is changed).
A primitive value is a datum that is represented at its lowest level of the language implementation and in JavaScript is one of the following types: number, string, Boolean, undefined, and null.
I read a book called "Professional Javascript for web developer" and it says: "Variable is assigned by Reference value or Primitive Value. Reference values are objects stored in memory". And then it says nothing about how Primitive value is stored. So I guess it isn't stored in memory. Based on that, when I have a script like this:
var foo = 123;
How does Javascript remember the foo variable for later use?
Okay, imagine your variable to be a piece of paper - a sticky note.
Note 1: A variable is a sticky note.
Now, a sticky note is very small. You can only write a little bit of information on it. If you want to write more information you need more sticky notes, but that's not a problem. Imagine you have an endless supply of sticky notes.
Note 2: You have an endless supply of sticky notes, which store small amounts of information.
Great, what can you write on your sticky note? I can write:
Yes or no (a boolean).
My age (a number).
My name (a string).
Nothing at all (undefined).
A doodle or anything else which means nothing to me at all (null).
So we can write simple things (let's be condescending and call them primitive things) on our sticky notes.
Note 3: You can write primitive things on your sticky notes.
So say I write 30 on a sticky note to remind myself to buy 30 slices of cheese for the little party I'm throwing at my place tonight (I have very few friends).
When I go to put my sticky note on the fridge I see that my wife has put another sticky note on the fridge which also says 30 (to remind me that her birthday is on the 30th of this month).
Q: Do both the sticky notes convey the same information?
A: Yes, they both say 30. We don't know if it's 30 slices of cheese or the 30th day of the month, and frankly, we don't care. For a person who didn't know any better, it's all the same.
var slicesOfCheese = 30;
var wifesBirthdate = 30;
alert(slicesOfCheese === wifesBirthdate); // true
Note 4: Two sticky notes which have the same thing written on them convey the same information, even though they are two different sticky notes.
I'm really excited about tonight - hanging out with old friends, having a great time. Then some of my friends call me and say that they won't be able to make it to the party.
So I go to my fridge and erase the 30 on my sticky note (not my wife's sticky note - that would make her very angry) and make it a 20.
Note 5: You can erase what's written on a sticky note and write something else.
Q: That's all good and fine, but what if my wife wanted to make write a list of groceries for me to pick up while I was out to get some cheese. Would she need to write a sticky note for every item?
A: No, she would take a long list of paper and write the list of groceries on that paper. Then she would write a sticky note telling me where to find the list of groceries.
So what's happening here?
A list of groceries is obviously not simple (erm... primitive) data.
My wife wrote it on a longer piece of paper.
She wrote where to find it in a sticky note.
Honey, the list of groceries is under your keyboard.
To recap:
The actual object (the list of groceries) is under my keyboard.
The sticky note tells me where to find it (the address of the object).
Note 6: Reference values are references to objects (addresses where they will be found).
Q: How do we know when two sticky notes say the same thing? Say my wife made another grocery list in case I misplaced the first, and wrote another sticky note for it. Both the lists say the same thing, but do the sticky notes say the same thing?
A: No. The first sticky note tells us where to find the first list. The second one tells us where to find the second list. It doesn't matter whether the two lists say the same thing. They are two different lists.
var groceryList1 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
var groceryList2 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
alert(groceryList1 === groceryList2); // false
Note 7: Two sticky notes convey the same information only if they refer to the same object.
This means if my wife made two sticky notes reminding me where the grocery list is, then the two sticky notes contain the same information. So this:
Honey, the list of groceries is under your keyboard.
Contains the same information as:
Don't forget that the list of groceries is under your keyboard.
In programming terms:
var groceryList1 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
var groceryList2 = groceryList1;
alert(groceryList1 === groceryList2); // true
So that's all that you need to know about primitives and references in JavaScript. No need to get into things like heap and dynamic memory allocation. That's important if you're programming in C/C++.
Edit 1: Oh, and the important thing is that when you pass variables around you're essentially passing primitive values by value and reference values by reference.
This is just an elaborate way of saying that you're copying everything written on one sticky note to another (it doesn't matter whether you're copying a primitive value or a reference).
When copying references, the object being referenced doesn't move (e.g. my wife's grocery list will always stay under my keyboard, but I can take the sticky note I copied anywhere I want - the original sticky note will still be on the fridge).
Edit 2: In response to the comment posted by #LacViet:
Well for starters we're talking about JavaScript, and JavaScript doesn't have a stack or a heap. It's a dynamic language and all the variables in JavaScript are dynamic. To explain the difference I'll compare it to C.
Consider the following C program:
#include <stdio.h>
int main() {
int a = 10;
int b = 20;
int c = a + b;
printf("%d", c);
return 0;
}
When we compile this program we get an executable file. The executable file is divided into multiple segments (or sections). These segments include the stack segment, the code segment, the data segment, the extra segment, etc.
The stack segment is used to store the state of the program when a function or interrupt handler is called. For example, when function f calls function g then the state of function f (all the values in the registers at that time) are saved in a stack. When g returns control to f then these values are restored.
The code segment holds the actual code to be executed by the processor. It contains a bunch of instructions the processor must execute like add eax, ebx (where add is the opcode, and eax & ebx are arguments). This instruction adds the contents of registers eax and ebx and stores the result in the register eax.
The data segment is used to reserve space for variables. For example, in the above program, we need to reserve space for the integers a, b and c. In addition, we also need to reserve space for the string constant "%d". Variables reserved thus have a fixed address in memory (after linking and loading).
In addition to all of these, you're also give a little bit of extra space by the Operating System. This is called the heap. Any extra memory you need is allocated from this space. Memory allocated in this way is called dynamic memory.
Let's see a program with dynamic memory:
#include <stdio.h>
#include <malloc.h>
int main() {
int * a = malloc(3 * sizeof(int));
a[0] = 3;
a[1] = 5;
a[2] = 7;
printf("a: %d\nb: %d\nc: %d\n", a[0], a[1], a[2]);
return 0;
}
Because we want to allocate memory dynamically we need to use pointers. This is because we want to use the same variable to point to an arbitrary memory location (not necessarily the same memory location every time).
So we create an int pointer (int *) called a. The space for a is allocated from the data segment (i.e. it's not dynamic). Then we call malloc to allocate the contiguous space for 3 integers from the heap. The memory address of the first int is returned and stored in the pointer a.
Q: What did we learn?
A: A fixed amount of space is allocated for all variables. Each variable has a fixed address. We may also allocate extra memory from the heap and store the address of this extra memory in a pointer. This is called a dynamic memory scheme.
Conceptually this is similar to what I explained about variables being sticky notes. All variables (including pointers are sticky notes). However, pointers are special because they reference a memory location (which is like referencing an object in JavaScript).
However, this is where the similarities end. Here are the differences:
In C everything is passed by value (including addresses in pointers). To pass a reference you need to use indirection via pointers. JavaScript only passes primitives by value. Passing references is handled transparently by the engine and is just like passing any other variable.
In C you can create a pointer to a primitive data type like int. In JavaScript, you cannot create a reference to a primitive value like number. All primitives are always stored by value.
In C you may perform various operations on pointers. This is called pointer arithmetic. JavaScript doesn't have pointers. It only has references. Thus you can't perform any pointer arithmetic.
Besides these three the biggest difference between C and JavaScript is that all variables in JavaScript actually pointers. Because JavaScript is a dynamic language the same variable may be used to store a number and a string at different points of time.
JavaScript is an interpreted language, and the interpreter is usually written in C++. Thus all variables in JavaScript are mapped to objects in the host language (even primitives).
When we declare a variable in JavaScript the interpreter creates a new generic variable for it. Then when we assign it a value (be it a primitive or a reference) the interpreter simply assigns a new object to it. Internally it knows which objects are primitive and which are actually objects.
Conceptually it's like doing something like this:
JSGenericObject ten = new JSNumber(10); // var ten = 10;
Q: What does this mean?
A: It means that all the values (primitives and objects) in JavaScript are allocated from the heap. Even the variables themselves are allocated from the heap. It's wrong to state that primitives are allocated from the stack and only objects are allocated from the heap. This is the biggest difference between C and JavaScript.
A variable can hold one of two value types: primitive values or reference values.
Primitive values are data that are stored on the stack.
Primitive value is stored directly in the location that the variable accesses.
Reference values are objects that are stored in the heap.
Reference value stored in the variable location is a pointer to a location in memory where the object is stored.
Primitive types include Undefined, Null, Boolean, Number, or String.
The Basics:
Objects are aggregations of properties. A property can reference an object or a primitive. Primitives are values, they have no properties.
Updated:
JavaScript has 6 primitive data types: String, Number, Boolean, Null, Undefined, Symbol (new in ES6). With the exception of null and undefined, all primitives values have object equivalents which wrap around the primitive values, e.g. a String object wraps around a string primitive. All primitives are immutable.
In javascript the Primitive values are data that are stored on the stack.
Primitive value is stored directly in the location that the variable accesses.
And the Reference values are objects that are stored in the heap.
Reference value stored in the variable location is a pointer to a location in memory where the object is stored.
JavaScript supports five primitive data types: number, string, Boolean, undefined, and null.
These types are referred to as primitive types because they are the basic building blocks from which more complex types can be built.
Of the five, only number, string, and Boolean are real data types in the sense of actually storing data.
Undefined and null are types that arise under special circumstances. The primitive type has a fixed size in memory.
For example, a number occupies eight bytes of memory, and a boolean value can be represented with only one bit.
And the Reference types can be of any length -- they do not have a fixed size.
A primitive type has a fixed size in memory. For example, a number occupies eight bytes of memory, and a boolean value can be represented with only one bit. The number type is the largest of the primitive types. If each JavaScript variable reserves eight bytes of memory, the variable can directly hold any primitive value.
This is an oversimplification and is not intended as a description of an actual JavaScript implementation.
Reference types are another matter, however. Objects, for example, can be of any length -- they do not have a fixed size. The same is true of arrays: an array can have any number of elements. Similarly, a function can contain any amount of JavaScript code. Since these types do not have a fixed size, their values cannot be stored directly in the eight bytes of memory associated with each variable. Instead, the variable stores a reference to the value. Typically, this reference is some form of pointer or memory address. It is not the data value itself, but it tells the variable where to look to find the value.
The distinction between primitive and reference types is an important one, as they behave differently. Consider the following code that uses numbers (a primitive type):
var a = 3.14; // Declare and initialize a variable
var b = a; // Copy the variable's value to a new variable
a = 4; // Modify the value of the original variable
alert(b) // Displays 3.14; the copy has not changed
There is nothing surprising about this code. Now consider what happens if we change the code slightly so that it uses arrays (a reference type) instead of numbers:
var a = [1,2,3]; // Initialize a variable to refer to an array
var b = a; // Copy that reference into a new variable
a[0] = 99; // Modify the array using the original reference
alert(b); // Display the changed array [99,2,3] using the new reference
If this result does not seem surprising to you, you're already well familiar with the distinction between primitive and reference types. If it does seem surprising, take a closer look at the second line. Note that it is the reference to the array value, not the array itself, that is being assigned in this statement. After that second line of code, we still have only one array object; we just happen to have two references to it.
As already mentioned in the accepted answer and the highest voted answer, primitive values are data that are stored in stack and reference values are object that are stored in heap.
But what does this actually mean? How do they perform differently in your codes?
Primitive values are accessed by value. So when you assign an variable (var a) that has a primitive value to another variable (var b), the value of the variable (a) gets copied into the new variable (b). And when you change the value of the new variable (b), the value of the original variable remain unchanged.
When you assign a variable (var x) that has a reference value to another variable (var y), the value stored in the variable (x) is also copied into the new variable (y). The difference is that the values stored in both variables now are the reference of the actual object stored in the heap. This means that, both x and y are pointing to the same object. So when you change the value of the new variable (y), the value of the original valuable (x) is also changed (because the actual object in the heap is changed).
A primitive value is a datum that is represented at its lowest level of the language implementation and in JavaScript is one of the following types: number, string, Boolean, undefined, and null.
I am working through a memory issue with one of our webapps. I am using Chrome's heap profiler. I want to make sure I understand something very explicitely, as I'm making assumptions on this information.
The # symbol in the heap profile screenshot above. I want to make sure I understand crystal clear: equal object ids implies the same object
a.objectId == b.objectId implies a same as b
a.objectId == b.objectId implies NOT a same as b
Therefore if I have two objects that I expected to actually be the same thing, yet their object id differs, this implies an unexpected copy occurred? This implies I can go and figure out in my code where I might be creating unnecessary duplicates?
The documentation appears to say this, but they don't quite say it explicitly, going on to say why they have an object id, not what it represents.
This is an object ID. Displaying an object's address makes no sense, as objects are moved during garbage collections. Those object IDs are real IDs — that means, they persist among multiple snapshots taken and are unique. This allows precise comparison between heap states. Maintaining those IDs adds an overhead to GC cycles, but it is only initiated after the first heap snapshot was taken — no overhead if heap profiles aren't used.
I get that. But I need to fit this back into my C programmer head. I realize, even with native heaps, pointer values can change over time. Can I effectively treat object ids as pointer addresses unique over time?
So I ran some test code in Chrome and the answer appears to be yes, the same object id implies identical objects. If object id differs, this implies a copy or different object altogether.
I profiled the following snippet of code which can be found in this github repo:
(function heapTest(doc) {
'use strict';
function clone(obj) {
return JSON.parse(JSON.stringify(obj));
}
var b = {'grandchild-key-2': 5};
var a = {'child-key-1': b};
doc.child1 = a;
doc.child1_again = a;
doc.child1_copy = clone(a);
})(document);
The heap profiler confirms the two references share object ids, the copy receives a new object id.
In short, this behaves like I expect. Multiple references to the same object receive the same object id. Copies refer to a different object and receive a different object id.
I read a book called "Professional Javascript for web developer" and it says: "Variable is assigned by Reference value or Primitive Value. Reference values are objects stored in memory". And then it says nothing about how Primitive value is stored. So I guess it isn't stored in memory. Based on that, when I have a script like this:
var foo = 123;
How does Javascript remember the foo variable for later use?
Okay, imagine your variable to be a piece of paper - a sticky note.
Note 1: A variable is a sticky note.
Now, a sticky note is very small. You can only write a little bit of information on it. If you want to write more information you need more sticky notes, but that's not a problem. Imagine you have an endless supply of sticky notes.
Note 2: You have an endless supply of sticky notes, which store small amounts of information.
Great, what can you write on your sticky note? I can write:
Yes or no (a boolean).
My age (a number).
My name (a string).
Nothing at all (undefined).
A doodle or anything else which means nothing to me at all (null).
So we can write simple things (let's be condescending and call them primitive things) on our sticky notes.
Note 3: You can write primitive things on your sticky notes.
So say I write 30 on a sticky note to remind myself to buy 30 slices of cheese for the little party I'm throwing at my place tonight (I have very few friends).
When I go to put my sticky note on the fridge I see that my wife has put another sticky note on the fridge which also says 30 (to remind me that her birthday is on the 30th of this month).
Q: Do both the sticky notes convey the same information?
A: Yes, they both say 30. We don't know if it's 30 slices of cheese or the 30th day of the month, and frankly, we don't care. For a person who didn't know any better, it's all the same.
var slicesOfCheese = 30;
var wifesBirthdate = 30;
alert(slicesOfCheese === wifesBirthdate); // true
Note 4: Two sticky notes which have the same thing written on them convey the same information, even though they are two different sticky notes.
I'm really excited about tonight - hanging out with old friends, having a great time. Then some of my friends call me and say that they won't be able to make it to the party.
So I go to my fridge and erase the 30 on my sticky note (not my wife's sticky note - that would make her very angry) and make it a 20.
Note 5: You can erase what's written on a sticky note and write something else.
Q: That's all good and fine, but what if my wife wanted to make write a list of groceries for me to pick up while I was out to get some cheese. Would she need to write a sticky note for every item?
A: No, she would take a long list of paper and write the list of groceries on that paper. Then she would write a sticky note telling me where to find the list of groceries.
So what's happening here?
A list of groceries is obviously not simple (erm... primitive) data.
My wife wrote it on a longer piece of paper.
She wrote where to find it in a sticky note.
Honey, the list of groceries is under your keyboard.
To recap:
The actual object (the list of groceries) is under my keyboard.
The sticky note tells me where to find it (the address of the object).
Note 6: Reference values are references to objects (addresses where they will be found).
Q: How do we know when two sticky notes say the same thing? Say my wife made another grocery list in case I misplaced the first, and wrote another sticky note for it. Both the lists say the same thing, but do the sticky notes say the same thing?
A: No. The first sticky note tells us where to find the first list. The second one tells us where to find the second list. It doesn't matter whether the two lists say the same thing. They are two different lists.
var groceryList1 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
var groceryList2 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
alert(groceryList1 === groceryList2); // false
Note 7: Two sticky notes convey the same information only if they refer to the same object.
This means if my wife made two sticky notes reminding me where the grocery list is, then the two sticky notes contain the same information. So this:
Honey, the list of groceries is under your keyboard.
Contains the same information as:
Don't forget that the list of groceries is under your keyboard.
In programming terms:
var groceryList1 = ["1 dozen apples", "2 loaves of bread", "3 bottles of milk"];
var groceryList2 = groceryList1;
alert(groceryList1 === groceryList2); // true
So that's all that you need to know about primitives and references in JavaScript. No need to get into things like heap and dynamic memory allocation. That's important if you're programming in C/C++.
Edit 1: Oh, and the important thing is that when you pass variables around you're essentially passing primitive values by value and reference values by reference.
This is just an elaborate way of saying that you're copying everything written on one sticky note to another (it doesn't matter whether you're copying a primitive value or a reference).
When copying references, the object being referenced doesn't move (e.g. my wife's grocery list will always stay under my keyboard, but I can take the sticky note I copied anywhere I want - the original sticky note will still be on the fridge).
Edit 2: In response to the comment posted by #LacViet:
Well for starters we're talking about JavaScript, and JavaScript doesn't have a stack or a heap. It's a dynamic language and all the variables in JavaScript are dynamic. To explain the difference I'll compare it to C.
Consider the following C program:
#include <stdio.h>
int main() {
int a = 10;
int b = 20;
int c = a + b;
printf("%d", c);
return 0;
}
When we compile this program we get an executable file. The executable file is divided into multiple segments (or sections). These segments include the stack segment, the code segment, the data segment, the extra segment, etc.
The stack segment is used to store the state of the program when a function or interrupt handler is called. For example, when function f calls function g then the state of function f (all the values in the registers at that time) are saved in a stack. When g returns control to f then these values are restored.
The code segment holds the actual code to be executed by the processor. It contains a bunch of instructions the processor must execute like add eax, ebx (where add is the opcode, and eax & ebx are arguments). This instruction adds the contents of registers eax and ebx and stores the result in the register eax.
The data segment is used to reserve space for variables. For example, in the above program, we need to reserve space for the integers a, b and c. In addition, we also need to reserve space for the string constant "%d". Variables reserved thus have a fixed address in memory (after linking and loading).
In addition to all of these, you're also give a little bit of extra space by the Operating System. This is called the heap. Any extra memory you need is allocated from this space. Memory allocated in this way is called dynamic memory.
Let's see a program with dynamic memory:
#include <stdio.h>
#include <malloc.h>
int main() {
int * a = malloc(3 * sizeof(int));
a[0] = 3;
a[1] = 5;
a[2] = 7;
printf("a: %d\nb: %d\nc: %d\n", a[0], a[1], a[2]);
return 0;
}
Because we want to allocate memory dynamically we need to use pointers. This is because we want to use the same variable to point to an arbitrary memory location (not necessarily the same memory location every time).
So we create an int pointer (int *) called a. The space for a is allocated from the data segment (i.e. it's not dynamic). Then we call malloc to allocate the contiguous space for 3 integers from the heap. The memory address of the first int is returned and stored in the pointer a.
Q: What did we learn?
A: A fixed amount of space is allocated for all variables. Each variable has a fixed address. We may also allocate extra memory from the heap and store the address of this extra memory in a pointer. This is called a dynamic memory scheme.
Conceptually this is similar to what I explained about variables being sticky notes. All variables (including pointers are sticky notes). However, pointers are special because they reference a memory location (which is like referencing an object in JavaScript).
However, this is where the similarities end. Here are the differences:
In C everything is passed by value (including addresses in pointers). To pass a reference you need to use indirection via pointers. JavaScript only passes primitives by value. Passing references is handled transparently by the engine and is just like passing any other variable.
In C you can create a pointer to a primitive data type like int. In JavaScript, you cannot create a reference to a primitive value like number. All primitives are always stored by value.
In C you may perform various operations on pointers. This is called pointer arithmetic. JavaScript doesn't have pointers. It only has references. Thus you can't perform any pointer arithmetic.
Besides these three the biggest difference between C and JavaScript is that all variables in JavaScript actually pointers. Because JavaScript is a dynamic language the same variable may be used to store a number and a string at different points of time.
JavaScript is an interpreted language, and the interpreter is usually written in C++. Thus all variables in JavaScript are mapped to objects in the host language (even primitives).
When we declare a variable in JavaScript the interpreter creates a new generic variable for it. Then when we assign it a value (be it a primitive or a reference) the interpreter simply assigns a new object to it. Internally it knows which objects are primitive and which are actually objects.
Conceptually it's like doing something like this:
JSGenericObject ten = new JSNumber(10); // var ten = 10;
Q: What does this mean?
A: It means that all the values (primitives and objects) in JavaScript are allocated from the heap. Even the variables themselves are allocated from the heap. It's wrong to state that primitives are allocated from the stack and only objects are allocated from the heap. This is the biggest difference between C and JavaScript.
A variable can hold one of two value types: primitive values or reference values.
Primitive values are data that are stored on the stack.
Primitive value is stored directly in the location that the variable accesses.
Reference values are objects that are stored in the heap.
Reference value stored in the variable location is a pointer to a location in memory where the object is stored.
Primitive types include Undefined, Null, Boolean, Number, or String.
The Basics:
Objects are aggregations of properties. A property can reference an object or a primitive. Primitives are values, they have no properties.
Updated:
JavaScript has 6 primitive data types: String, Number, Boolean, Null, Undefined, Symbol (new in ES6). With the exception of null and undefined, all primitives values have object equivalents which wrap around the primitive values, e.g. a String object wraps around a string primitive. All primitives are immutable.
In javascript the Primitive values are data that are stored on the stack.
Primitive value is stored directly in the location that the variable accesses.
And the Reference values are objects that are stored in the heap.
Reference value stored in the variable location is a pointer to a location in memory where the object is stored.
JavaScript supports five primitive data types: number, string, Boolean, undefined, and null.
These types are referred to as primitive types because they are the basic building blocks from which more complex types can be built.
Of the five, only number, string, and Boolean are real data types in the sense of actually storing data.
Undefined and null are types that arise under special circumstances. The primitive type has a fixed size in memory.
For example, a number occupies eight bytes of memory, and a boolean value can be represented with only one bit.
And the Reference types can be of any length -- they do not have a fixed size.
A primitive type has a fixed size in memory. For example, a number occupies eight bytes of memory, and a boolean value can be represented with only one bit. The number type is the largest of the primitive types. If each JavaScript variable reserves eight bytes of memory, the variable can directly hold any primitive value.
This is an oversimplification and is not intended as a description of an actual JavaScript implementation.
Reference types are another matter, however. Objects, for example, can be of any length -- they do not have a fixed size. The same is true of arrays: an array can have any number of elements. Similarly, a function can contain any amount of JavaScript code. Since these types do not have a fixed size, their values cannot be stored directly in the eight bytes of memory associated with each variable. Instead, the variable stores a reference to the value. Typically, this reference is some form of pointer or memory address. It is not the data value itself, but it tells the variable where to look to find the value.
The distinction between primitive and reference types is an important one, as they behave differently. Consider the following code that uses numbers (a primitive type):
var a = 3.14; // Declare and initialize a variable
var b = a; // Copy the variable's value to a new variable
a = 4; // Modify the value of the original variable
alert(b) // Displays 3.14; the copy has not changed
There is nothing surprising about this code. Now consider what happens if we change the code slightly so that it uses arrays (a reference type) instead of numbers:
var a = [1,2,3]; // Initialize a variable to refer to an array
var b = a; // Copy that reference into a new variable
a[0] = 99; // Modify the array using the original reference
alert(b); // Display the changed array [99,2,3] using the new reference
If this result does not seem surprising to you, you're already well familiar with the distinction between primitive and reference types. If it does seem surprising, take a closer look at the second line. Note that it is the reference to the array value, not the array itself, that is being assigned in this statement. After that second line of code, we still have only one array object; we just happen to have two references to it.
As already mentioned in the accepted answer and the highest voted answer, primitive values are data that are stored in stack and reference values are object that are stored in heap.
But what does this actually mean? How do they perform differently in your codes?
Primitive values are accessed by value. So when you assign an variable (var a) that has a primitive value to another variable (var b), the value of the variable (a) gets copied into the new variable (b). And when you change the value of the new variable (b), the value of the original variable remain unchanged.
When you assign a variable (var x) that has a reference value to another variable (var y), the value stored in the variable (x) is also copied into the new variable (y). The difference is that the values stored in both variables now are the reference of the actual object stored in the heap. This means that, both x and y are pointing to the same object. So when you change the value of the new variable (y), the value of the original valuable (x) is also changed (because the actual object in the heap is changed).
A primitive value is a datum that is represented at its lowest level of the language implementation and in JavaScript is one of the following types: number, string, Boolean, undefined, and null.