- It creates a brand new object.
- The new object gets linked to the function's prototype.
- The new object gets passed into the function call as
this
. - The function call returns
this
.
It is a function call with the new
keyword in front of it.
It performs the first two actions that using the new
keyword does:
- It creates a brand new object.
- The new object gets linked to another object.
It's a linkage from one object to another and it's created at the time the object is created. (When an object is created it gets linked somewhere.)
If we call methods or properties on an object and they don't exist, the prototype will attempt to look higher up the prototype chain for the desired behavior.
foo.__proto__
Object.getPrototypeOf
foo.constructor.prototype
You lose encapsulation because each property and method is public.
We love classes, and the prototype pattern seems to be the best way we have in Javascript to emulate classes.
The prototype system and the lexical system do not cross over.
The syntax is beautiful!
But it's just syntactic sugar over the prototype system. They're designed to pretend there is a copy operation going on because that's they way classes work in other languages.
The power of javascript is to be able to create objects, link them together, and delegate between them.
var Foo = {
init: function(who) {
this.me = who;
},
identify: function() {
return `I am ${this.me}`;
}
};
var Bar = Object.create(Foo);
Bar.speak = function() {
console.log(`Hello, ${this.identity()}!`);
}
var b1 = Object.create(Bar);
b1.init('Sweet');
b1.speak();
if (!Object.create) {
Object.create = function(o) {
return {
__proto__: o
};
};
}
if (!Object.create) {
Object.create = function(o) {
function F() {};
F.prototype = o;
return new F();
};
}
It's a pattern where we decide to delegate objects to one another at the call site.
Each piece of code is independent. This makes testing MUCH easier.
Here's an example:
var AuthController = {
authenticate() {
server.authenticate(
[this.username, this.password],
this.handleResponse.bind(this)
);
},
handleResponse(resp) {
if (!resp.ok) this.displayError(resp.msg);
}
};
var LoginFormController =
delegateTo(AuthController, {
onSubmit() {
this.username = document.querySelector("#username").textContent;
this.password = document.querySelector("#password").textContent;
this.authenticate();
},
displayError(msg) {
alert(msg)
}
});
function delegateTo(delegate, body) {
if (body === undefined) body = {};
return Object.assign(Object.create(delegate), body);
}
The prototype chain provides a live link up the chain instead of copying objects down the chain.
Delegate is peer-to-peer rather than parent-child. We don't inherit behavior, but we collaborate with other objects that can provide the behavior we're looking for.
Delegation allows two objects to share context at call time. (Virtual composition.)
Since objects are composed together, it is much easier to test objects in isolation.
The code is more explicit.
We lost encapsulation that we had in the module pattern.
The code can be a little more complex.