Difference between prototype constructor and private property
Consider the first scenario:
function f(){
console.log("inside the function : " + f.myVar);
}
f.prototype.myVar = 1;
var myObject = new f();
console.log("from the object : " + myObject.myVar);
And this is the result:
inside the function : undefined
from the object : 1
Question: why is myVar not available in a function? If stored in prototype objects, it must be available in f ().
Now this script:
function f(){
console.log("inside the function : " + this.myVar);
}
f.prototype.myVar = 1;
var myObject = new f();
console.log("from the object : " + myObject.myVar);
And the output is:
inside the function : 1
from the object : 1
Question: Why do I get a different result? if 'this' refers to an object, doesn't f.myVar mean accessing myVar to myObject?
And now this script:
function f(){
console.log("inside the function : " + f.myVar);
console.log("inside the function using 'this' : " + this.myVar);
}
f.myVar = 1;
var myObject = new f();
console.log("from the object : " + myObject.myVar);
output:
inside the function : 1
inside the function using 'this' : undefined
from the object : undefined
So if I set a property without using a prototype, it shouldn't be available on the instantiated objects. But if I write the script like this, it produces a weird result:
function f(){
console.log("inside the function : " + f.myVar);
}
f.myVar = 1;
var myObject = new f();
console.log("from the first object : " + myObject.myVar);
var strangeObject = myObject.constructor;
console.log("from the strange object : " + strangeObject.myVar);
Output:
inside the function : 1
from the first object : undefined
from the strange object : 1
Where is this "f.myVar" stored? Whose variable is this? I am confused what the difference is between all the scenarios above. Full confirmation would be much appreciated.
EDIT:
The main problem is that I don't know what exactly this means:
function f(){}
f.someVar = someValue;
Because in other languages, a function is an abstract concept and doesn't actually exist before it is called. Now JS says that functions are objects by default. So, I must have an object like this using the script above:
{someVar : sameValue}
In fact, I think it should be the same as:
function f(){this.someVar = someValue;} //should create {someVar : someValue}
If so, every object created when "new f ()" is called must contain this "someVar", but they don't.
source to share
why is myVar not available in a function? If stored in objects the prototype is assumed to be available in f ().
It is available in a function, but not as f.myVar
, but as this.myVar
or f.prototype.myVar
.
Why am I getting different results? if 'this' refers to an object doesn't f.myVar mean accessing myVar to myObject?
The function is f
not the same as an object instance. This function is an object constructor, and using it with the keyword new
creates an instance that is a separate object from the function.
When you use f.var
it is a property var
of the function object. When you use it this.var
in a function, it is the property var
on the object instance where the keyword is used new
.
If you use f.var
then this is a property of the constructor function object, so it will be the same variable even if you create multiple instances of the object and is only accessible with f.var
.
If you use f.prototype.var
it will also be a variable that will be the same for all instances of the object, but can also be accessed using this.var
, since the object inherits from the prototype members.
Example:
function f() {
console.log(f.var); // shows "42"
console.log(f.prototype.var); // shows "0.01"
console.log(this.var); shows "0.01";
}
f.var = 42;
f.prototype.var = 0.01;
If you want a variable to be local to every instance of an object, you shouldn't use any of them. You have to assign a value this.var
that will make it a property on the object instance.
Example:
function f(value) {
this.var = value;
}
f.prototype.getValue = function(){
return this.var;
};
var instance1 = new f(42);
var instance2 = new f(0.01);
// now you have two instances with separate values:
console.log(instance1.getValue()); // shows "42"
console.log(instance2.getValue()); // shows "0.01"
source to share
Start by exploring the definition of a word prototype. I think it's important to keep this in mind when thinking about how new objects are created in JavaScript.
pro k type
noun
- the first, typical or preliminary model of something, especially a machine from which other shapes are designed or copied.
verb
- make a prototype (of a product).
A prototype is a model from which another shape will be copied.
When you create a new object in JavaScript, this is exactly what happens.
var obj = new MyObject();
There are many things going on in the above code, but in the context of the question, there are two things that matter:
- The prototype is applied to the new object.
- The MyObject function is called, with
this
a new object set.
With this knowledge in mind, let's take a look at the different forms of variable definition that you described:
function MyObject() {}
MyObject.myProperty = 'MyProperty';
It is important to understand that the functions themselves are objects in JavaScript. Therefore, it function MyObject
is an instance of an object for itself. In the second line, we set a property myProperty
on this function object.
Refer to the creation steps above and you will notice that it does not include applying the properties of the function object to a new instance of the object. It will only apply the prototype properties of the function object and then runs the function body with this
set to a new instance.
function MyObject() {
this.myProperty = 'MyProperty';
}
Here the property myProperty
is set in a separate instance.
function MyObject() {}
MyObject.prototype.myProperty = 'MyProperty';
In this example, each new instance MyObject
will be assigned its own property myProperty
and value set to 'MyProperty'
. From there, each instance can change its own myProperty
to any of its values ββwithout affecting the other.
function MyObject() {
console.log('myProperty', this.myProperty); //Will output 'Outside constructor.'
this.myProperty = 'Inside constructor.';
console.log('myProperty', this.myProperty); //Will output 'Inside constructor.
}
MyObject.prototype.myProperty = 'Outside constructor.';
The example above shows how it is myProperty
first applied from the prototype and then overwritten by the value in the function being executed.
Let's look at an example with all the forms you specified:
var output1 = document.getElementById('output1'),
output2 = document.getElementById('output2'),
output3 = document.getElementById('output3');
function MyObject(myProperty) {
this.myProperty = myProperty;
}
MyObject.myProperty = 'Function property.';
MyObject.prototype.myProperty = 'Prototype property.';
var obj = new MyObject('Constructor property');
output1.innerHTML = obj.myProperty;
output2.innerHTML = MyObject.myProperty;
output3.innerHTML = MyObject.prototype.myProperty;
<div id="output1"></div>
<div id="output2"></div>
<div id="output3"></div>
In the example above, you will see how each can be referenced. Now let's take a closer look at it. See what happens to your Function Property when it is set from two different object instances:
var output1 = document.getElementById('output1'),
output2 = document.getElementById('output2');
function MyObject() {
//We are concatenating a string to the end of the property on each function call.
MyObject.myProperty += ' test ';
}
MyObject.myProperty = 'Function property.';
var obj1 = new MyObject();
var obj2 = new MyObject();
output1.innerHTML = MyObject.myProperty;
output2.innerHTML = MyObject.myProperty;
<div id="output1"></div>
<div id="output2"></div>
The above code demonstrates how function level property is efficiently allocated. This is because it is not part of every instance. It is part of a functional object.
Here, I'll show you the process that goes with the operator new
, without actually using the operator new
:
var output = document.getElementById('output');
//Let have an object that has a prototype property with some properties:
var MyPrototypeObject = {
prototype: {
myPrototypeProperty: 'Prototype property'
}
};
//Let specify a function that will be used as a constructor:
function MyConstructorFunction() {
this.myInstanceProperty = 'Instance property';
}
//First, new creates an object
var obj = {};
//Next, it applies all the properties from the prototype. We are using the MyPrototypeObject prototype property for this example
for (var key in MyPrototypeObject.prototype) {
var val = MyPrototypeObject.prototype[key];
//Set the same property on the new object.
obj[key] = val;
}
//Now the prototype has been applied, let apply the constructor function that was called.
MyConstructorFunction.call(obj); //This calls MyConstructorFunction with this set to obj.
output.innerHTML = 'myPrototypeProperty: ' + obj.myPrototypeProperty + '<br>' + 'myInstanceProperty: ' + obj.myInstanceProperty;
<div id="output"></div>
source to share
As for the question in the board, it's actually simple :-)
you have a function object function f(){}
you add a property to this object, for example you can add a property to any other object in javascript f.someVar = 1
this is not the case function f(){this.someVar = someValue;}
because this
in javascript it depends on how the function is called and can refer to the instantiated object, the global object, or whatever if called with a function call
or apply
.
When you create an object with an operator, new
you call f
as a constructor, in which case the inner function this
refers to the created object, and all properties added inside the function are this.something = val
added to the created object.
Note: that you are not using any property from the function directly, so this is not added to the created object.
As for prototype
: when creating an object, you just set the property of the prototype
created object to the object f.prototype
. So in the end when you create the object you are not using any property directly added to the function object, just a property from the prototype and a property added manually in this
in the constructor
source to share
You seem to be confused with the function and object prototype.
Here is a quote from Eloquent Javascript explaining the difference:
It is important to note the difference between a prototype associated with a constructor (via its prototype property) and prototypes have a prototype (which can be obtained using Object.getPrototypeOf). The actual prototype of the constructor is Function.prototype, since constructors are functions. Its prototype property will be the prototype of the instances created through it, not its own prototype.
source to share