Note: This is not a question about classical and prototype inheritance. It's about what coding patterns to use to initialize objects. Class constructors create and initialize objects, whereas avoiding the new
operator and going for Object.create()
only creates the object and sets up the prototype chain. I have not yet found an online resource that explains best-practice coding patterns for doing creation and initialization when going for the Crockford Object.create()
approach.
If I have a constructor (in my head this makes my class, although I know classes don't technically exist yet in mainstream JavaScript)
function Person(first, last) {
this.name = {
first: first,
last: last
};
}
Person.prototype.tellName = function() {
return this.name.first + ' ' + this.name.last;
}
I can then instantiate it like this
var p1 = new Person('John', 'Doe');
var p2 = new Person('Sven', 'Svensson');
And change the Person.name.first
and Person.name.last
separately
p1.tellName(); // Output: 'John Doe'
p2.tellName(); // Output: 'Sven Svensson'
p1.name.first = 'Peter';
p2.name.last = 'Celery';
And execute the object's function Person.tellName()
with the following output
p1.tellName(); // Output: 'Peter Doe'
p2.tellName(); // Output: 'Sven Celery'
Which is very similar to how I'd approach building such a class in C++ or Java.
Object.create()
-ish) approach instead of new
?E.g.
...
// some code that does the same stuff as defining a class + constructor
...
var p1 = ???????
var p2 = ???????
// The following is the code and behavior I'm looking to get
p1.tellName(); // Output: 'John Doe'
p2.tellName(); // Output: 'Sven Svensson'
p1.name.first = 'Peter';
p2.name.last = 'Celery';
p1.tellName(); // Output: 'Peter Doe'
p2.tellName(); // Output: 'Sven Celery'
Instead of having:
function Person(first, last) {
this.name = {
first: first,
last: last
};
}
Person.prototype.tellName = function() {
return this.name.first + ' ' + this.name.last;
}
You'd just have:
function Person(first, last) {
return {
name: { first: first, last: last },
tellName: function() { return this.name.first + ' ' + this.name.last; }
};
};
Or, if you prefer how person.create()
looks, then:
var person = {
create: function(first, last) {
return {
name: { first: first, last: last },
tellName: function() { return this.name.first + ' ' + this.name.last; }
};
}
};
But in the second case you'd have an unnecessary object (person
) containing only one function (person.create()
).
No need for Object.create
nor new
since those are for inheritance which you said you do not care about. This would let you do:
var p1 = Person('John', 'Doe');
var p2 = Person('Sven', 'Svensson');
A fun fact is that you can still use new
in front of person.create
this way if you want but it would offer no effect. If you have to use the existing function you can set the this
context explicitly by using .call
// with your original `Person`
var p1 = Person.call({}, 'John', 'Doe');
var p2 = Person.call({}, 'Sven', 'Svensson');
This would not set the prototype either since the function is not called like a constructor. See this answer about what prototypical answer does and doesn't do - in a line it's about sharing functionality it's not about constructing properties of your objects.
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