What are the benefits / drawbacks of functional object creation in JavaScript? - javascript

I just watched Douglas Crockford talk about how prototypical inheritance is "not a good idea either"
YouTube 35m55s
I don't really care about his views on Prototypical inheritance in conjunction with JavaScript since it is such an essential part of the language that it will always be there.
But I would like to know what benefits I am reaping by using the functional object creation that he is showing in the link:
// Class Free Object Oriented Programming
function constructior(init) {
var that = other_constructor(init),
member,
method = function () {
// init, member, method
};
that.method = method;
return that;
}
After the video I re-read the part about Functional Object Creation in his book "JavaScript The Good Parts" Chapter 5: Inheritance.
But I can't really see the big difference..
I can get private members just fine with the constructor pattern:
function Constructor (value) {
var private = value;
this.getPrivate = function () {
return private;
}
}
var OBJ1 = new Constructor(5);
var OBJ2 = new Constructor('bacon');
console.log( OBJ1.getPrivate() ); // 5
console.log( OBJ2.getPrivate() ); // bacon
The only difference I can spot between a Constructor Pattern and the Functional Pattern is the omission of the new keyword. By avoiding the use of the new keyword we can avoid the error of forgetting the new keyword.
Writing this:
var panda = createBear();
Instead of this:
var panda = new Bear();
Makes me think it is mainly down to personal preference. I can see how avoiding the new keyword can be useful, and I might adopt it the functional pattern.
But this is the only reason I can see as to why you would do it. Can I please get some more information why one would be better or worse than the other?

Alright so I am gonna try and answer my own question here with the information that I have received and additional stuff I have gathered on the internet after asking the question.
TL;DR:
They are both useful and can achieve mostly the same things. Constructors have access to their prototype which can be very useful because it means they have "global" values across all its instances created with the Constructor. It is both useful and potentially dangerous. Useful because all the instances of the Constructor will have access to the same prototype property thus avoiding duplication. Dangerous because you can override the constructor property OR give the instance a property of the same name - making it harder to access the prototypes value.
There is some danger of forgetting new keyword when calling the Constructor but it is easily remedied by adding "use strict"; inside the Constructor function which will then throw an error if you forget the new keyword.
If you want to avoid the Prototype and its features/dangers you can use a Factory
Function.
The really useful Feature of the Functional approach is that you can return anything you like. Rather than always Constructing a "child" of a predefined object.
What I have learned from all this is that it is stupid to pick one over the other when you could be using both. They both have their strengths and weaknesses and people need to remember that Douglas Crockford is just a human being, not the JavaScript God. (That would be Brandon Eich, lol jk!)
The accepted answer by #Domenic on What difference is there in JavaScript between a constructor function, and function returning object which is invoked as a constructor?
Gave me some insights on the differences and similarities between the two methods of object creation.
Constructor
Using the new keyword creates a link between the new object and the Constructor Object it is derived from. The Constructor is the Prototype of the new Object and the new Object is an instance of the Prototype Object.
var Constructor = function () {
this.x = 0;
this.y = 0;
};
var A = new Constructor();
console.log(A instanceof Constructor ); // true
Being linked to the prototype object means that our new object has access to the prototypes properties without having to store them inside the object itself. This is both more memory efficient than creating the properties on each child object and it comes with the added bonus of the power of Prototyping.
Adding a property or method to the object prototype is simple:
Constructor.prototype.color = 'yellow';
Now every object created with the Constructor object has access to the .color property without storing it inside themselves.
var A = new Constructor();
console.log(A.color); // yellow
console.log(A.hasOwnProperty('color')); // false
Since the objects in JavaScript are dynamic it means that you can "retroactively" add new properties to the prototype and objects created before the change will still "inherit" the new properties.
var A = new Constructor();
Constructor.prototype.food = 'bacon';
console.log(A.food); // bacon;
One reason that Crockford might advocate against the Constructor patters is to avoid overriding the prototype property OR overriding the namespace of the prototype inside the child object accidentally.
Constructor.prototype.number = 5;
A.calculate = function () {
return A.number * 5;
}
console.log(A.calculate()); // 25
Constructor.prototype.number = 'fishsticks';
console.log(A.calculate()); // NaN
From what I can understand adding properties after creation will also make the code run slower inside the V8 engine because the objects no longer share the same "hidden classes" But I am not knowledgeable enough to get into that. Breaking the JavaScript Speed Limit with V8
The prototype can still be accessed. Either via the now deprecated .__proto__. or the newObject.getPrototypeOf() method.
console.log(Object.getPrototypeOf(A.color)); // yellow
The other reason why Crockford is advocating against the use of a Constructor Function is that you might forget to type new. If you forget to write new in front of the Constructor it will run the Constructor Function instead of creating a new object.
var A = Constructor();
console.log(A); // undefined
This is easily fixed by adding strict typing to your function which will throw an error if you forget the new keyword.
var Constructor = function () {
"use strict";
this.x = 0;
this.y = 0;
}
var A = Constructor();
console.log(A);
// Uncaught TypeError: Cannot set property 'x' of undefined
Factory Function
I found this pretty straight forward. If you don't want to have deal with the new keyword, and some of the "dangers" of the Constructor function, you can create objects that don't use their prototype with this approach.
function factory () {
var obj = {
x: 0,
y: 0
}
return obj;
}
var A = factory(); // {x: 0, y: 0}
This can be very handy for when you want to do something with the data other than just creating an Object.
function factory () {
if ( new Date().getHours() < 8 ) {
return "can't create object. Need Coffe!"
};
var obj = {
x: 0,
y: 0
}
return obj;
}
var A = factory(); // Before 8 am: "can't create object. Need Coffe!"
var A = factory(); // After 8 am: {x: 0, y: 0};
Doing this you lose the power / danger of the prototype. Because the object is not bound to one.
factory.prototype.foo = "bar";
A = factory();
console.log(A.foo); // undefined
This means you can't use it. But it also means you can't mess it up.
In conclusion.
See TL;DR
I learned a lot searching and writing this, hopefully someone else will learn a thing or two too.
References:
What difference is there in JavaScript between a constructor function, and function returning object which is invoked as a constructor?
Constructor function vs Factory functions
It’s time to start using JavaScript strict mode

Related

If JavaScript doesn't support Classical inheritance why am I able to create constructors and use new keyword?

According to MDN javascript only support prototypical inheritance. Yet I can do the following:
function Human() {
this.eyes = 2;
this.feet = 2;
}
Var Mark = new Human();
What's even more confusing, I can add a method to the constructor using .prototype keyword:
Human.prototype.walk = function(distance) {
//code
}
Yet there's a proper way to create objects using Object.Create which is apparently the proper prototype based object creation:
var Human = {
eyes: 2,
feets: 2
}
var Mark = Object.create(Human);
Can someone please clear this up for me? Thank you
The first thing you should understand is that the snippet you've provided as an example is still prototypal inheritance, and here's why:
Human is a function which contains a prototype object. Instances of Human extend that prototype object with their own data initialized in the Human constructor.
The prototype object can be modified at runtime. Even after you've created instances of the class, you can still modify their inherited behavior by adding or changing properties on the prototype object. None of this is possible with classical inheritance.
In classical inheritance, there is a distinct difference between a class and an object. In prototypal inheritance, classes are merely an object that is a constructable function, meaning it can be invoked with the new keyword, but otherwise, can be treated like any other object.
Given this information, let's demonstrate a few key similarities and differences between Object.create() and new:
function Human() {
this.eyes = 2;
this.feet = 2;
}
Human.prototype.walk = function () { };
var josh = new Human();
console.log(josh);
var human = {
constructor: function Human() {
this.eyes = 2;
this.feet = 2;
},
walk: function () { }
};
// create josh with prototype of human
var josh = Object.create(human);
// initialize own properties by calling constructor
human.constructor.call(josh); // or josh.constructor();
console.log(josh);
It may not look it at first, but these two snippets are actually creating an instance josh with the exact same layout:
{
eyes: 2,
feet: 2,
__proto__: {
walk: f (),
constructor: f Human(),
__proto__: Object.prototype
}
}
That is to say:
var proto = Object.getPrototypeOf(josh);
var protoProto = Object.getPrototypeOf(proto);
console.log(proto === Human.prototype); // or proto === human
console.log(protoProto === Object.prototype);
<- true
<- true
This demonstrates the prototype chain of josh. It is the path of inheritance that determines the behavior of the object, and shows that josh inherits from Human, which inherits from Object.
The difference between the two Stack Snippet consoles above is due to the fact that the first snippet's constructor is a non-enumerable property of Human.prototype, while the second snippet's constructor is an enumerable property of human.
If you want to pick apart the second snippet, I highly suggest taking a closer look at the documentation for Object.create() on MDN, and possibly even glancing at the specification for it if you can grok the dense language.
Here's how you can use Object.create() with our definition of Human instead:
function Human() {
this.eyes = 2;
this.feet = 2;
}
Human.prototype.walk = function () { };
// create prototypal inheritance
var josh = Object.create(Human.prototype);
// initialize own properties
Human.call(josh); // or josh.constructor();
console.log(josh);
This initializes the instance properties of the instance josh by calling the ES5 constructor with josh as the context (the this keyword).
Lastly, since it was mentioned in comments, all of this can be abstracted for simplicity using the ES6 class keyword, which still uses prototypal inheritance:
class Human {
constructor() {
this.eyes = 2;
this.feet = 2;
}
walk() { }
}
var josh = new Human();
console.log(josh);
The output may appear different but if you check in the real Developer Console, you'll find that the only difference in the layout of josh is due to the fact that ES6 classes declare member methods like walk() as non-enumerable properties of Human.prototype, which is why it doesn't show up in the Stack Snippet console.
You cannot use Object.create() the same way as demonstrated in ES5 because an ES6 class is only constructable (invoke-able with new) and not callable (invoke-able without new):
class Human {
constructor() {
this.eyes = 2;
this.feet = 2;
}
walk() { }
}
var josh = Object.create(Human.prototype); // still works
// no own properties yet because the constructor has not been invoked
console.log(josh);
// cannot call constructor to initialize own properties
Human.call(josh); // josh.constructor(); would not work either
Addendum
I tried to come up with a way to more easily see the prototype chain of objects in the Stack Snippet console, so I wrote this function layout(). It recurses into an object's prototype chain and makes all the properties enumerable. Since prototype chains cannot have cycles, this can never get stuck in infinite recursion:
// makes all properties in an object's prototype chain enumerable
// don't worry about understanding this implementation
function layout (o) {
if (typeof o !== 'object' || !o || o === Object.prototype) return o;
return [...Object.getOwnPropertyNames(o), '__proto__'].reduce(
(a, p) => Object.assign(a, { [p]: layout(o[p]) }),
Object.create(null)
);
}
// this is intentionally one line in order to
// make Stack Snippet Console output readable
function HumanES5() { this.eyes = 2; this.feet = 2; }
HumanES5.prototype.walk = function () { };
var josh = new HumanES5();
console.log(layout(josh));
var josh = Object.create(HumanES5.prototype);
HumanES5.call(josh); // or josh.constructor();
console.log(layout(josh));
class HumanES6 {
constructor () { this.eyes = 2; this.feet = 2; }
walk () { }
}
var josh = new HumanES6();
console.log(layout(josh));
var josh = Object.create(HumanES6.prototype);
// HumanES6.call(josh); will fail, remember?
console.log(layout(josh));
.as-console-wrapper{min-height:100%!important}
There are two things to note here.
In the last two outputs, class HumanES6 { ... } actually refers to the constructor function in the class declaration. In prototypal inheritance, the class and its constructor are synonymous.
The last output doesn't have the own properties eyes and feet since the constructor was never invoked to initialize that instance of josh.
You can use new because the language specification defined it that way. The creators of JavaScript could also have omitted the possibility of using the new keyword or Object.create().
new does not in and of itself suggest anything about inheritance; it could also exist in languages with no inheritance at all. It just happens to be a keyword to create a new "object" in JavaScript.
And depending on the language, new has different meanings. It could just define the creation of a new object, but could also include the meaning of where/how to allocate the memory, and/or about what is responsible for the memory lifecycle.
A classical inheritance based language could work without a new keyword at all. Or it could have a deprecated new keyword in favor of a better way to create objects in a newer version of the language.
You could conceive various ways of creating a new object from a descriptor:
new Descriptor(arg1, arg2);
Descriptor obj(arg1, arg2);
obj = Descriptor.alloc().init(arg1, arg2);
obj = Descriptor.new(arg1, arg2);
obj = create(Descriptor, arg1, arg2);
...
All of those could have slightly different meanings in different languages. So you should not bother too much if one language borrows a keyword or concept from another language, because most of the time they differ in minor (or even critical) details.
So use your previous knowledge to aid in learning the new language, but don't try too hard to perfectly synonymize these concepts between different languages. You have to keep in mind that other languages have different concepts even if they look similar. Therefore, it is often helpful to simply accept it as given by the specs.

new instance has old values in javascript inheritance and prototyping [duplicate]

What does the following code do:
WeatherWidget.prototype = new Widget;
where Widget is a constructor, and I want to extend the Widget 'class' with a new function WeatherWidget.
What is the new keyword doing there and what would happen if it is left out?
WeatherWidget.prototype = new Widget;
The new keyword calls Widget as a constructor and the return value is assigned to the prototype property. (If you would omit new, you would not call Widget unless you added an argument list, (). However, calling Widget that way might not be possible. It would certainly have the potential to spoil the global namespace if it is not strict mode code and the implementation is conforming to ECMAScript Ed. 5.x there, because then this in the constructor would refer to ECMAScript’s global object.)
But this approach actually comes from a really viral bad example in the old Netscape JavaScript 1.3 Guide (mirrored at Oracle, formerly Sun).
This way, your WeatherWidget instances will all inherit from the same Widget instance. The prototype chain will be:
[new WeatherWidget()] → [new Widget()] → [Widget.prototype] → …
This can be useful, but most of the time you would not want it to happen. You should not do that here unless you want all your WeatherWidget instances to share among them the property values they inherit from this Widget instance, and only through it, from Widget.prototype. Another problem is that you need to call the parent constructor this way, which may not allow to be called without arguments as you do, or would not initialize properly. It certainly has nothing to do with emulation of class-based inheritance as known, e.g., from Java.
The proper way to implement class-based inheritance in these prototype-based languages is (originally devised by Lasse Reichstein Nielsen in comp.lang.javascript in 2003, for cloning objects):
function Dummy () {}
Dummy.prototype = Widget.prototype;
WeatherWidget.prototype = new Dummy();
WeatherWidget.prototype.constructor = WeatherWidget;
The constructor prototype property should be fixed as well, so that your WeatherWidget instances w would have w.constructor === WeatherWidget as expected, and not w.constructor === Widget. However, be aware that it is enumerable afterwards.
This way, WeatherWidget instances will inherit properties through the prototype chain, but will not share property values among them, because they inherit from Widget.prototype through Dummy which has no own properties:
[new WeatherWidget()] → [new Dummy()] → [Widget.prototype] → …
In implementations of ECMAScript Ed. 5 and later, you can and should use
WeatherWidget.prototype = Object.create(Widget.prototype, {
constructor: {value: WeatherWidget}
});
instead. This has the additional advantage that the resulting constructor property is not writable, enumerable, or configurable.
The parent constructor will only be called if you call it explicitly, from WeatherWidget, for example with
function WeatherWidget (…)
{
Widget.apply(this, arguments);
}
See also Function.prototype.extend() in my JSX:object.js for how to generalize this. Using that code, it would become
WeatherWidget.extend(Widget);
My Function.prototype.extend() takes an optional second argument with which you can easily augment the prototype of WeatherWidget instances:
WeatherWidget.extend(Widget, {
foo: 42,
bar: "baz"
});
would be equivalent to
WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";
You will still need to call the parent constructor explicitly in the child constructor, though; that part cannot reasonably be automated. But my Function.prototype.extend() adds a _super property to the Function instance which makes it easier:
function WeatherWidget (…)
{
WeatherWidget._super.apply(this, arguments);
}
Other people have implemented similar extensions.
According to some odd Javascript rules, new Widget actually invokes the constructor rather than returning a reference to the constructor. This question actually answers the question the difference between var a = new Widget() and var a = Widget().
In simple words, the new keyword tells Javascript to call the function Widget under a different set of rules than a regular function call. Going off the top of my head, the ones I remember are:
There is a brand new object created
Widget can use the this keyword to refer to that object.
If Widget does not return anything, this new object will be created.
This object will inherit a few additional properties that will indicate it was created by Widget that are used to track down property chains.
Without the new keyword, a call to widget would
If in strict mode, this will be set to undefined.
Otherwise, this will refer to the global object. (Called window by the browser.)
If the function does not return anything, then undefined will be returned.
Reference:
new keyword
WeatherWidget.prototype = new Widget;
does create a new instance of the Widget constructor and use it as WeatherWidget's prototype object. Using the new keyword creates the new object, sets up the inheritance chain of it to Widget.prototype, and applies the constructor function on it (where you can set up individual properties'n'methods, or create private-scoped variables).
Without the new keyword it would be an assignment of the Widget function to the prototype property - which does not make any sense. If you'd add the optional brackets (i.e. Widget()), it would invoke the function normally, but not as a constructor on a new instance, but with the global object as context. See also the reference for the this keyword.
Notice that you should not really use this code. As said, it creates a new instance by invoking the constructor function. But the purpose is only to create an empty object that inherits from the Widgets prototype object, not to instantiate something (which could do some harm, depending on the code). Instead, you should use Object.create (or its popular shim):
WeatherWidget.prototype = Object.create(Widget.prototype);
see also Javascript basic inheritance vs Crockford prototypical inheritance
In plain english you're extending one class with another. A prototype can only be an object so you set WeatherWidget's prototype to a new instance of Widget. If you removed the new keyword you would be setting the prototype to the literal constructor function which doesn't do anything.
var Appendages = function(){
this.legs = 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = new Appendages;
var sara = new Features();
sara.legs;
// Returns 2.
Understanding that the prototype can be any object, something like this would also work:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
In JavaScript, if the key isn't found on the object, it checks the parents object you extended it from. Hence you can change items on the parent object on the fly like so:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
appendages.hair = true;
sara.hair;
// Returns true.
Note that this all happens during instantiation which means you can't just switch out the prototype after you've created the object:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.prototype = bar;
foo.nachos;
// undefined
However, all modern browsers come with this newer __proto__ method, which allows you to do it:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.__proto__ = bar;
foo.nachos
// "cheese"
Read up more on understanding JavaScript prototypes here.
This article from Pivotal Labs is also really good.
new is important for prototype inheritance; i.e.
Create a constructor with a method
var Obj = function(){};
Obj.prototype = {};
Obj.prototype.foo = function(){console.log('foo');};
Make a second constructor to extend the first with
var ExObj = function(){};
Now, if we prototype without new,
ExObj.prototype = Obj;
(new ExObj).foo(); // TypeError: Object #<Object> has no method 'foo'
Which means we haven't inherited from the prototype of Obj, however, if we prototype with new
ExObj.prototype = new Obj();
(new ExObj).foo(); // console logs 'foo'
Furthermore, adding new things to the prototype of ExObj doesn't make any changes to it's base, Obj.
JavaScript functions are "MULTIPLE(2) PERSONALITIES"!!!
They are regular-functions with input and output, which we call like function().
Also they are constructors of JS-objects, when we use the new keyword. >>>BUT<<< the new created objects are NOT INSTANCES of the constructors (like the objects of classes in class-based inheritance). The new objects are instances of the object of the prototype property of the constructor.
Then in WeatherWidget.prototype = you put the object you want to inherit its properties to the objects the constructor will create, which usually is new function() and not a function.
JavaScript created HUGE confusion in the programming community by naming the objects created by constructors, INSTANCES of them with the instanceof keyword.
> function f(){}
undefined
> new f() instanceof f
true

Purpose of this Javascript prototype snippet

Sorry I can't phrase this better. But I ran across some code like the following:
MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;
And I just can't seem to figure out what it does. MyObject is defined above it something like this:
function MyObject(options) {
this.someProp = someDefault;
this.otherProp = process(options.something);
// etc...
}
and it's always called as a constructor. I'm just wondering what benefit those first two lines provide and if it's a known pattern in Javascript.
I just can't seem to figure out what it does
It creates a new object that inherits from [the old] MyObject.prototype via Object.create and then overwrites MyObject.prototype with that. It also explicitly adds a .constructor property which actually should be existing already.
I'm just wondering what benefit those first two lines provide
None, unless before that snippet someone has corrupted the prototype (like MyObject.prototype = Object.prototype) and this is an attempt to fix it.
…and if it's a known pattern in Javascript.
Not like this. Using Object.create to set up the prototype chain for inheritance between constructor-defined "classes" is a known pattern, but then the constructors would be different on each side of the assignment.
The two lines of code provided seem to be an incorrect attempt of the use of prototypal inheritance, but I see where you're going with this and what you're trying to accomplish.
As we know, there are two ways in JavaScript to define objects that have properties and methods as members - the object literal notation and function notation. Using object literal notation, we don't have immediate access to the new keyword (think of this like using abstract classes in Java or C#). With function notation, we have access to the new keyword because the initial declaration of an object as a function serves as our constructor.
In ECMAScript 5, The Object object was given a method called create that provided developers a simple way to create a new object from an existing object declared with the object literal notation. (See documentation here). However, objects created in function notation have problems with this method because they are Function objects. The Object.create method is a great way to use simple inheritance, allowing access to the base properties and methods.
With function notation, once the new keyword is used, the result is not a function, but rather an object. For example, I can test this:
var Obj = function(){};
console.log(typeof Obj) // "function"
console.log(typeof new Object()); // "object"
Because of this, you can only inherit once (meaning the child object cannot be derived from):
var MyObject = new Object();
var anotherObj = new MyObject() // throws exception
To alleviate this problem, you need to follow three steps:
Create your child object in function notation (so you can create new instances of it using the new keyword and inherit from it).
Set the child object's prototype (an object) to the result of a new instance of the base object (which will be an object as well).
Set the constructor of the child object (which happens to be on the object's prototype) back to reference the Function of itself (which is a function prior to instantiation). If you don't do this, the constructor will remain an object, which cannot spawn new instances.
From here, you can create new instances of both the child and parent objects and derive from both, using the pattern. Here's a practical example:
var Vehicle = function(){};
Vehicle.prototype.start = function() {
return this.make + " " + this.model + " " + "started";
}
var Car = function(color, make, model) {
this.color = color;
this.make = make;
this.model = model;
}
Car.prototype = new Vehicle();
Car.prototype.constructor = Car;
var myCar = new Car("red", "chevy", "aveo");
myCar.start(); //"chevy aveo started"
I really don't see any benefit in doing that.
What it's doing is providing the new object with the previous objects methods. But it's coming from the same object...
Here is a good example of JS inheritance:
http://jsfiddle.net/aDCmA/2/
var App = (function(){
var Being = function() {
this.living = true;
this.breathes = function () {
return true;
};
};
var Robert = function() {
this.blogs = true;
this.getsBored = function () {
return "You betcha";
}
};
Robert.prototype = new Being();
return {
Being: Being,
Robert: Robert,
being: function(){ return new Being(); },
robert: function(){ return new Robert(); }
}
}());
Here is another question that is similar: inherit prototype methods from other classes without overriding own prototype methods
Credit to Robert Nyman for originally blogging about it: http://robertnyman.com/2008/10/06/javascript-inheritance-how-and-why/
Let's see line by line:
MyObject.prototype = Object.create(MyObject.prototype);
This redefines MyObject.prototype to an object that inherits from MyObject.prototype. This is unusual, because it makes no sense to inherit from itself.
MyObject.prototype.constructor = MyObject;
Since the previous line overwrote MyObject.prototype, this is just fixing the constructor property that was lost in the process.
I can think of one scenario where tht might be useful: if some code before that messed up with MyObject.prototype, for example assigning the prototype of another constructor to it:
MyObject.prototype = SomethingElse.prototype; // wrong way to do inheritance.
Then the code you posted would be an attempt to fix it.
This is perfectly valid Javascript.
Any javascript function (say Func)can be used as a constructor and the constructor invocation also requires a prototype property (i.e. F.prototype or the prototype associated with the function) . Thus (almost) every function has a prototype property. The value of this property (i.e. Func.prototype).
Now the value of this prototype associated with the function is an object itself that has a single non enumerable property called constructor. And the value of this constructor property is the function object (i.e. F itself).
Lets take an example.
Say I construct a function Func
var Func = function() {
//your definition
};
Now since this can be invoked as a constructor it has to have a prototype property Func.prototype lets call this proto.
proto = Func.prototype;
Now the prototype has a single property (that is non enumerable) called constructor. This constructor has a value that is equal to the function object itself.
Dont believe me check it like this
Func.prototype.constructor === Func // =>true
Will always return true for any function.
Now from the code you explained :
So basically these two lines
MyObject.prototype = Object.create(MyObject.prototype);
MyObject.prototype.constructor = MyObject;
are modifying the value of the prototye to have a constructor property with the value of MyObject that is defined. But that would have happened anyways in the normal course of things. But the reason could be that maybe the prototype of the object has been changed earlier from the class it has been inherited from. In that case would those two lines make sense.
Hope that helps :)

What is the reason to use the 'new' keyword at Derived.prototype = new Base

What does the following code do:
WeatherWidget.prototype = new Widget;
where Widget is a constructor, and I want to extend the Widget 'class' with a new function WeatherWidget.
What is the new keyword doing there and what would happen if it is left out?
WeatherWidget.prototype = new Widget;
The new keyword calls Widget as a constructor and the return value is assigned to the prototype property. (If you would omit new, you would not call Widget unless you added an argument list, (). However, calling Widget that way might not be possible. It would certainly have the potential to spoil the global namespace if it is not strict mode code and the implementation is conforming to ECMAScript Ed. 5.x there, because then this in the constructor would refer to ECMAScript’s global object.)
But this approach actually comes from a really viral bad example in the old Netscape JavaScript 1.3 Guide (mirrored at Oracle, formerly Sun).
This way, your WeatherWidget instances will all inherit from the same Widget instance. The prototype chain will be:
[new WeatherWidget()] → [new Widget()] → [Widget.prototype] → …
This can be useful, but most of the time you would not want it to happen. You should not do that here unless you want all your WeatherWidget instances to share among them the property values they inherit from this Widget instance, and only through it, from Widget.prototype. Another problem is that you need to call the parent constructor this way, which may not allow to be called without arguments as you do, or would not initialize properly. It certainly has nothing to do with emulation of class-based inheritance as known, e.g., from Java.
The proper way to implement class-based inheritance in these prototype-based languages is (originally devised by Lasse Reichstein Nielsen in comp.lang.javascript in 2003, for cloning objects):
function Dummy () {}
Dummy.prototype = Widget.prototype;
WeatherWidget.prototype = new Dummy();
WeatherWidget.prototype.constructor = WeatherWidget;
The constructor prototype property should be fixed as well, so that your WeatherWidget instances w would have w.constructor === WeatherWidget as expected, and not w.constructor === Widget. However, be aware that it is enumerable afterwards.
This way, WeatherWidget instances will inherit properties through the prototype chain, but will not share property values among them, because they inherit from Widget.prototype through Dummy which has no own properties:
[new WeatherWidget()] → [new Dummy()] → [Widget.prototype] → …
In implementations of ECMAScript Ed. 5 and later, you can and should use
WeatherWidget.prototype = Object.create(Widget.prototype, {
constructor: {value: WeatherWidget}
});
instead. This has the additional advantage that the resulting constructor property is not writable, enumerable, or configurable.
The parent constructor will only be called if you call it explicitly, from WeatherWidget, for example with
function WeatherWidget (…)
{
Widget.apply(this, arguments);
}
See also Function.prototype.extend() in my JSX:object.js for how to generalize this. Using that code, it would become
WeatherWidget.extend(Widget);
My Function.prototype.extend() takes an optional second argument with which you can easily augment the prototype of WeatherWidget instances:
WeatherWidget.extend(Widget, {
foo: 42,
bar: "baz"
});
would be equivalent to
WeatherWidget.extend(Widget);
WeatherWidget.prototype.foo = 42;
WeatherWidget.prototype.bar = "baz";
You will still need to call the parent constructor explicitly in the child constructor, though; that part cannot reasonably be automated. But my Function.prototype.extend() adds a _super property to the Function instance which makes it easier:
function WeatherWidget (…)
{
WeatherWidget._super.apply(this, arguments);
}
Other people have implemented similar extensions.
According to some odd Javascript rules, new Widget actually invokes the constructor rather than returning a reference to the constructor. This question actually answers the question the difference between var a = new Widget() and var a = Widget().
In simple words, the new keyword tells Javascript to call the function Widget under a different set of rules than a regular function call. Going off the top of my head, the ones I remember are:
There is a brand new object created
Widget can use the this keyword to refer to that object.
If Widget does not return anything, this new object will be created.
This object will inherit a few additional properties that will indicate it was created by Widget that are used to track down property chains.
Without the new keyword, a call to widget would
If in strict mode, this will be set to undefined.
Otherwise, this will refer to the global object. (Called window by the browser.)
If the function does not return anything, then undefined will be returned.
Reference:
new keyword
WeatherWidget.prototype = new Widget;
does create a new instance of the Widget constructor and use it as WeatherWidget's prototype object. Using the new keyword creates the new object, sets up the inheritance chain of it to Widget.prototype, and applies the constructor function on it (where you can set up individual properties'n'methods, or create private-scoped variables).
Without the new keyword it would be an assignment of the Widget function to the prototype property - which does not make any sense. If you'd add the optional brackets (i.e. Widget()), it would invoke the function normally, but not as a constructor on a new instance, but with the global object as context. See also the reference for the this keyword.
Notice that you should not really use this code. As said, it creates a new instance by invoking the constructor function. But the purpose is only to create an empty object that inherits from the Widgets prototype object, not to instantiate something (which could do some harm, depending on the code). Instead, you should use Object.create (or its popular shim):
WeatherWidget.prototype = Object.create(Widget.prototype);
see also Javascript basic inheritance vs Crockford prototypical inheritance
In plain english you're extending one class with another. A prototype can only be an object so you set WeatherWidget's prototype to a new instance of Widget. If you removed the new keyword you would be setting the prototype to the literal constructor function which doesn't do anything.
var Appendages = function(){
this.legs = 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = new Appendages;
var sara = new Features();
sara.legs;
// Returns 2.
Understanding that the prototype can be any object, something like this would also work:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
In JavaScript, if the key isn't found on the object, it checks the parents object you extended it from. Hence you can change items on the parent object on the fly like so:
var appendages = {
legs : 2
};
var Features = function() {
this.ears = 4;
this.eyes = 1;
}
// Extend Features class with Appendages class.
Features.prototype = appendages;
var sara = new Features();
sara.legs;
// Returns 2.
appendages.hair = true;
sara.hair;
// Returns true.
Note that this all happens during instantiation which means you can't just switch out the prototype after you've created the object:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.prototype = bar;
foo.nachos;
// undefined
However, all modern browsers come with this newer __proto__ method, which allows you to do it:
var foo = {name : 'bob'};
var bar = {nachos : 'cheese'};
foo.__proto__ = bar;
foo.nachos
// "cheese"
Read up more on understanding JavaScript prototypes here.
This article from Pivotal Labs is also really good.
new is important for prototype inheritance; i.e.
Create a constructor with a method
var Obj = function(){};
Obj.prototype = {};
Obj.prototype.foo = function(){console.log('foo');};
Make a second constructor to extend the first with
var ExObj = function(){};
Now, if we prototype without new,
ExObj.prototype = Obj;
(new ExObj).foo(); // TypeError: Object #<Object> has no method 'foo'
Which means we haven't inherited from the prototype of Obj, however, if we prototype with new
ExObj.prototype = new Obj();
(new ExObj).foo(); // console logs 'foo'
Furthermore, adding new things to the prototype of ExObj doesn't make any changes to it's base, Obj.
JavaScript functions are "MULTIPLE(2) PERSONALITIES"!!!
They are regular-functions with input and output, which we call like function().
Also they are constructors of JS-objects, when we use the new keyword. >>>BUT<<< the new created objects are NOT INSTANCES of the constructors (like the objects of classes in class-based inheritance). The new objects are instances of the object of the prototype property of the constructor.
Then in WeatherWidget.prototype = you put the object you want to inherit its properties to the objects the constructor will create, which usually is new function() and not a function.
JavaScript created HUGE confusion in the programming community by naming the objects created by constructors, INSTANCES of them with the instanceof keyword.
> function f(){}
undefined
> new f() instanceof f
true

Baffling JavaScript Inheritance Behavior

<disclaimer>
What follows is the fruits of a thought experiment. What I'm doing
isn't the issue; the symptoms are. Thank you.
</disclaimer>
I've finally wrapped my head around constructors, prototypes, and prototypal inheritance in JavaScript. But the SomethingSpectactular method in the sample below bugs me:
function FinalClass() {
return {
FinalFunction : function() { return "FinalFunction"; },
TypeName : "FinalClass",
SomethingSpectacular : function() {
return FinalClass.prototype.SubFunction.call(this);
}
}
}
FinalClass.prototype = new SubClass();
FinalClass.constructor = FinalClass;
var f = new FinalClass();
The reasons this bugs me are:
JavaScript apparently doesn't scan the prototype chain the same way for methods as it does for properties. That is, f.SubFunction() generates an error.
To get to a method on a prototype, you have to go through at least 3 dot operations every time you want to do it. FinalClass DOT prototype DOT Subfunctino DOT call. You get the point.
Base class (prototype) methods aren't showing up in Intellisense the way I'd expect them to. This is highly annoying.
So the thought experiement was to determine what would happen if I wrote a version of inherits that inserted stub functions onto the subclass that delegated back to the prototype for you. For example, it would automatically create the following function and add it to FinalClass:
function SubFunction() { SubClass.prototype.SubFunction.call(this); }
Now, I've got just about everything mapped out and working. The inherits method, which is an extension to both Object.prototype and Function.prototype, takes a Function as its sole argument. This is the base class. The subclass is determined by analyzing Object.prototype.inherits.caller.
From there, I set the prototype and constructor on the subclass, and then start analyzing the methods on the subclass's new prototype. I build an array containing the methods on both the prototype and the base class's public interface. The end result is a nice array that contains the methods that are exposed through either the prototype or by the base class constructor's return statement.
Once I have that, I start looking for each method on the subclass. If it's not there, I add it to the subclass with the same name and signature. The body of the method, however, simply forwards the call to the base class.
Now, I can step through all this code and it works marvelously, up until I instantiate instances of the subclasses. That's when things get wonky. Here's what I've observed using Visual Studio 2008 (SP1) and Internet Explorer 8:
Prior to instantiation, BaseClass exposes no public methods. This is to be expected. The methods exposed via a class constructor's return statement won't appear until it's instantiated. I'm good with that.
Prior to instantiation, SubClass exposes the methods from BaseClass. This is exactly what I expected.
Once I declare an instance of BaseClass, it has all the members I would expect. It has its typeName and BaseFunction methods.
Once I declare an instance of SubClass, it has only those methods returned by its constructor's return statement. No members from the base class are present. All the work that was done in the inherits method to map base class methods to the subclass appears to have been lost.
The big mystery for me here is the disappearance of the methods that I added to SubClass during the execution of inherits. During its execution, I can clearly see that SubClass is being modified, and that BaseClass's functions are being propagated. But the moment I create an instace of SubClass, that information is no longer present.
I am assuming this has something to do with the constructor, or order of events, or something else that I am simply not seeing.
A Final Note: This project arose as an effort to understand the complexities of JavaScript and how its prototypal inheritance system works. I know there are existing libraries out there. I know I'm reinventing the wheel. I'm reinventing it on purpose. Sometimes, the best way to understand a thing is to build it yourself. This has already been a tremendous learning experience, but I'm just stumped at this one particular point.
THE CODE
sti.objects.inherits = function inherits(baseClass) {
var subClass = sti.objects.inherits.caller;
var baseClassName = sti.objects.getTypeName(baseClass);
var methods = sti.objects.getMethods(baseClass);
if(!sti.objects.isDefined(baseClass.typeName))
baseClass.typeName = baseClassName;
var subClass = sti.objects.inherits.caller;
var subClassName = sti.objects.getTypeName(subClass);
var temp = function() {};
temp.prototype = new baseClass();
subClass.prototype = temp.prototype;
subClass.constructor = subClass;
subClass.typeName = subClassName;
subClass.baseClass = baseClass.prototype; // Shortcut to the prototype's methods
subClass.base = baseClass; // Cache the constructor
for(var index = 0; index < methods.items.length; index++) {
var resource = methods.items[index].getFunction();
var methodName = methods.items[index].getName();
if(methodName != "" && ! sti.objects.isDefined(subClass[methodName])) {
var method = sti.objects.createOverride(baseClassName, resource);
subClass[methodName] = method;
if(typeof subClass.prototype[methodName] == "undefined") {
subClass.prototype[methodName] = method;
}
}
}
}
Object.prototype.inherits = sti.objects.inherits;
Function.prototype.inherits = sti.objects.inherits;
function BaseClass() {
return {
A : function A() {return "A";}
};
}
function SubClass() {
inherits(BaseClass);
return {
B : function B() { return "B"; }
}
}
var b = new BaseClass();
var s = new SubClass();
Your constructors are not working as constructors. When you use the new keyword Javascript creates the new object and expects your constructor to populate it with members etc. Your constructors are returning another new object, not related to the object which is associated with the constructor usage, thus the prototype is not working.
Change your constructor to something like
function FinalClass() {
this.FinalFunction = function() { return "FinalFunction"; };
this.TypeName = "FinalClass";
this.SomethingSpectacular = function() {
return FinalClass.prototype.SubFunction.call(this);
};
}
and you should see the expected inheritance behaviour. This is because the FinalClass method in this case alters the contextual object created via the 'new' mechanism. Your original method is creating another object which is not of type FinalClass.

Categories

Resources