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 output:
inside the function : undefined
from the object : 1
Question: why myVar isn't available in function? If it is stored in the objects prototype it is supposed to be accessible in f().
Now this scenario:
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:
inside the function : 1
from the object : 1
Question: Why I'm getting different result? if 'this' refers to the object doesn't f.myVar mean access myVar in myObject ?
And now this scenario:
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 prototype it should'nt be available in instantiated objects. But if I write the script like this, it'll deliver a strange 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 does that "f.myVar" store? Whose variable is that? I'm confused what is the difference between all scenarios above. A complete carification would be much appreciated.
EDIT:
The main problem is that I don't know what this exactly mean:
function f(){}
f.someVar = someValue;
Because in other languages function is an abstract concept and in fact doesn't exist until it is called. Now in JS it is said that functions are objects by default. Ok so I should have an object like this by the script above:
{someVar : sameValue}
in fact I think this should be as same as:
function f(){this.someVar = someValue;} //should create {someVar : someValue}
If this is the case EVERY object instantiated by calling "new f()" must contain this "someVar" but they don't.
Start out by examining the definition of the word prototype. I think it's important to keep this in mind when thinking about how new objects are created in JavaScript.
pro·to·type
noun
verb
A prototype is a model from which another form will be copied.
When you create a new object in JavaScript, that is exactly what happens.
var obj = new MyObject();
In the above code, there are many things that happen, but in the context of the question, there are two things that happen which are relevant:
this set to the new object.With this knowledge in mind, let's take a look at the different forms of setting variables you have described:
function MyObject() {}
MyObject.myProperty = 'MyProperty';
It's important to understand that functions themselves are objects in JavaScript. Therefore, function MyObject is an object instance to itself. On the second line, we have set the property myProperty on this function object.
Refer back to the steps of creation above, and you will notice that it does not include applying properties from the function object to the new instance object. It only applies properties from the function object's prototype, and then runs the body of the function with this set to the new instance.
function MyObject() {
this.myProperty = 'MyProperty';
}
Here, the property myProperty is set on the individual instance.
function MyObject() {}
MyObject.prototype.myProperty = 'MyProperty';
In this example, each new instance of MyObject will be given its own property called myProperty and the value set to 'MyProperty'. From there, each instance can change its own myProperty to whatever value it needs 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 above example shows how myProperty is first applied from the prototype, then overwritten by the value applies in the function that is run.
Let's take a look at an example with all the forms you mentioned:
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 above example, you'll see how each can be referenced. Now examine it a little closer. Take a look at what happens with 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 the function level property is effectively shared. That's because it's not part of each instance. It's part of the function object.
Here I'll show you the process that takes place with the new operator, without actually using the new operator:
var output = document.getElementById('output');
//Let's have an object that has a prototype property with some properties:
var MyPrototypeObject = {
prototype: {
myPrototypeProperty: 'Prototype property'
}
};
//Let's 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's 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's 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>
why myVar isn't available in function? If it is stored in the objects prototype it is supposed to be accessible in f().
It's accessible in the function, but not as f.myVar, but as this.myVar or f.prototype.myVar.
Why I'm getting different result? if 'this' refers to the object doesn't f.myVar mean access myVar in myObject ?
The function f is not the same as the object instance. The function is the constructor for the object, and using it with the new keyword creates an instance that is a separate object from the function.
When you use f.var, that is the property var of the function object. When you use this.var in the function, that is the property var in the object instance that the use of the new keyword created.
If you use f.var, that 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 it's only accessible using f.var.
If you use f.prototype.var, that will also be a variable that is the same for all instances of the object, but that can also be accessed using this.var as the object inherits the members of the prototype.
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 that is local to each instance of the object, you should use neither of those. You should assign a value to this.var, which will make it a property in 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"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With