Reputation: 440
What is the difference between adding a property to a function object vs, adding a property to the objects prototype. See code below.
var foo = function() { this.name = alert("test") };
foo.newProp = function() { ... };
var value = new foo();
// vs
foo.prototype.newProp = function() { ... }
var value = new foo();
My confusion is what happens to value when this code is run for each, AND how 'this' is affected.
Upvotes: 0
Views: 334
Reputation:
Since functions are objects, case 1 is nothing more than adding a property to an object. Case 2 is more interesting. Consider the following code :
function f (name) {
this.name = name;
}
f.prototype.sayHello = function () {
console.log("Hello I'm " + this.name + " !");
};
var x = new f("X");
var y = new f("Y");
<button type="button" onclick="x.sayHello()">x.sayHello()</button>
<button type="button" onclick="y.sayHello()">y.sayHello()</button>
Note that there is nothing like x.sayHello = function () {...}
in this code. Think of it twice and ask yourself :
Since
x.sayHello
is never explicitly defined, what is the underlying mechanism that preventsx.sayHello()
from crashing the program ?
That is the question.
Fortunately, there is nothing magical, only JavaScript internal processing. Indeed, when you create an object with new
, or when you call a function, there is something happening behind the scene in which the prototype
property is involved.
When you write new f()
, the JavaScript engine :
this
to the new object.f
.__proto__
to the new object.__proto__
to f.prototype
.When you write x.sayHello()
, the JavaScript engine :
x
.sayHello
is found.x.__proto__
otherwise.sayHello
is found.this
to x
.sayHello
.Key points to highlight :
new
keyword, JavaScript creates a prototype chain, i.e. the engine performs the following task : x.__proto__ = f.prototype
.x.sayHello()
, if JavaScript fails to find sayHello
into x
, it looks into x.__proto__
which is f.prototype
.this
depends on the context. For example, when you write x.sayHello()
, this
is x
, when you write y.sayHello()
, this
is y
, when you write new f()
, this
is a new object. More about this
.Custom implementation :
function instanciate (f, args) {
var object = {};
f.apply(object, args);
object.__proto__ = f.prototype;
return object;
}
function execute (object, fName, args) {
var f = lookup(object, fName);
if (typeof f !== "function") {
throw "not a function";
} else {
f.apply(object, args);
}
}
function lookup (object, key) {
do {
if (object.hasOwnProperty(key)) {
return object[key];
} else {
object = object.__proto__;
}
}
while (object !== null);
}
function f (name) {
this.name = name;
}
f.prototype.sayHello = function () {
console.log("Hello I'm " + this.name + " !");
};
var x = instanciate(f, ["X"]);
var y = instanciate(f, ["Y"]);
<button
type="button"
onclick="execute(x, "sayHello")"
>execute(x, "sayHello")</button>
<button
type="button"
onclick="execute(y, "sayHello")"
>execute(y, "sayHello")</button>
The global object is not special :
f.prototype.__proto__ = window.__proto__;
window.__proto__ = f.prototype;
name = "John Doe";
sayHello(); // "Hello I'm John Doe !"
Upvotes: 3
Reputation: 4523
Firstly, we know that functions are nothing but objects as we can attach properties to it. That is what is happening in the case1.
We are just simply attaching a property to a function Foo
Case 1
var Foo = function(){
this.name = "myname";
}
Foo.newProp = function(){};
The property attached to the function can be simply accessed as how we access properties of an object.
Case 2
In this case the same property is sitting on the prototype
of that function. When any object is created using this function Foo
, it will get access to this function by default.
When calling the function using that object, the context this
will know the object calling that function and this
points to the object calling it.
Foo.prototype.newProp = function(){ console.log("function on prototype");}
var value = new Foo();
console.log(value);
Also in case 2, since we are adding properties to the prototype of the function, they are not sitting on the object made using that function but on the proto of that object. Check this screenshot shown below:
That means there is a common memory location to which every object accessing that property will be pointing and hence it is memory efficient as well.
You can always go ahead and modify that property by overriding it by defining it directly on the object as:
value.newProp = function(){ console.log("modified property") };
Now, if you call this function, it will find it directly on the object and wont go down the prototype chain to access it from the common memory location i.e prototype of the function Foo
Upvotes: 2
Reputation: 15292
foo.newProp = function() { ... };?
This will define function at function(class) level.
You can access it directly without using object.
foo.newProp() // call it.
foo.prototype.newProp = function() { ... };?
Its define the newProp
at instance level(object or class instance
).
You need define the object using new
then only you will able to access it.
var value = new foo();
value.newProp() // call it
By defining the function using prototype,you make it available to all already + newly defined object the given function
Upvotes: 0