EDITED
What is the difference in doing:
var a = function(){};
a.myProperty = function(){};
Versus:
var a = function(){};
a.prototype.myProperty = function(){};
I realise this might be a silly or vague question but what do I need to understand to know the difference between the two and when to use one over the other?
Note that the question has been heavily edited since it was first posed, which is why the existing comment and answer make no sense.
All functions have prototypes. The methods attached to these prototypes are available to instances of objects created by calling the function as a constructor. So in the second example, if you write var o = new a(); then you will be able to invoke o.myProperty();.
Additionally all functions are objects, so you can set arbitrary properties directly on the function itself, as per the first example. You can also access the function from the object using o.constructor (or this.constructor from a member function). This could be used to implement the equivalent of C++ static class variables.
There is no difference. Your setting a property on an object.
Note that your second example fails because you havn't set a.prototype to a value.
Of course if you made a a function then it gets a prototype property by default.
And that .prototype property has a special property. If you invoke new someFunction then the [[Prototype]] of the return value is someFunction.prototype.
This only applies if .prototype is a property of a function. Since new only works on functions.
Related
I have this function here, I need to work with this other function called OrderRepository in another file.
main.js
function main() {
var orderRepo = new OrderRepository();
// Your code here
}
orderrepository.js
function OrderRepository() {
}
OrderRepository.prototype.getYesterdaysOrders = function
getYesterdaysOrders() {
var yesterdaysOrders = [{ array of objects }],
return yesterdaysOrders;
};
These were given as examples to use, 1 question rolled into 2 parts:
1) var orderRepo = new OrderRepository();
Can you initialize a function like this?
2) In the orderrepository.js:
function OrderRepository() {
}
is being called in main.js, but nothings inside of it, this was given as-is in the assignment, is this just a typo and really they meant to throw everything inside that function or am I missing something?
Shouldn't it look like this?
Expected
function OrderRepository() {
OrderRepository.prototype.getYesterdaysOrders = function
getYesterdaysOrders() {
var yesterdaysOrders = [{ array of objects }],
return yesterdaysOrders;
};
}
Diving deeper into JavaScript, the language is hard to understand. JavaScript is not really OOP (imho), at least it does not implement the common OOP concept. Some call it object-based language. There are no classes. Recent ECMA Script standards do implement the class keyword, however, it is syntax sugar. Used with the new keyword it builds the same objects as you can achieve by 'constructor' functions.
Everything in JavaScript is an object, even numbers and functions. Every function can act as constructor function. The new keyword call a constructor function with a newly creates empty object as the function's this context. The function can do what it wants. If it does not return anything, its this context is returned by the new expression.
Since there are no classes, there is no inheritance. Some inheritance-like behavior is achieved by the prototype concept. In most cases the constructor will return nothing and sometimes modify the this object by adding properties. Methods are properties holding a function object. The object in the new context of a constructor call will have a prototype object reference as the __proto__ property. This is copied by the new operator from the prototype property of the called constructor function. The default is an empty object.
// empty constructor function
function OrderRepository() {
}
// define a function property on the constructor's prototype object
OrderRepository.prototype.getYesterdaysOrders = function
getYesterdaysOrders() {
var yesterdaysOrders = [ /* array of objects */ ],
return yesterdaysOrders;
};
// create an empty object with a `__proto__` property holding a
// reference to the object { getYesterdaysOrders: function(){/*code*/} }
var obj = new OrderRepository();
Now, when the method invocation obj.getYesterdaysOrders() is tried, JavaScript will look if there is such a property defined in obj. If not, it looks if there is a reference in obj.__proto__ and the property name is searched the properties of obj.__proto__. If not, the same step is repeated until it was found or the __proto__ property in the chain is null. Since obj.__proto__.getYesterdaysOrders is defined, it is checked if it is a callable function object and finally invoked with a this context of obj since we called obj.getYesterdaysOrders(). Otherwise an error is thrown.
NOTE: Even if the major browsers do expose the __proto__ property, it is not part of the standards. Do not use it directly (except for debugging at development time) and even more important: do not manipulate it. If you really need to get or manipulate a prototype (__proto__) of an object instance after construction, use the methods of the builtin Object object.
Upon your last edit: Your expected code would define a new function object in prototype on each instantiation (and thus constructor invocation). This is not what you want, it's just needless overhead.
Regarding the first part, it looks like this assignment is dealing with how to create instances of objects in JavaScript as that is what the new operator does.
You can find more information regarding new on the MDN.
Regarding the second question, it is dealing with how to create objects that inherit methods. So, yes it is empty, until you get to the prototype expression.
The expected code would not give you the inheritance in this case. Notice how OrderRepository is repeated inside the function, which would be invalid. Javascript requires you to add inheritance to the special prototype property. Code that is added to the function declaration, would be scoped to the function only in that case.
You can find more information about prototype on the MDN.
I found this picture here
In this case, foo is a constructor function and B and C are objects. I am very confused, first off when you create an object does it always come with the properties and proto? Is that the default? Also in terms of the constructor function for foo. Am I correct to say that every proto of a function defaults to Function.prototype, which uses Object.prototype to create an object? The part that is confusing for me is Foo.prototype, when was this prototype created? Does a constructor function always default to the creation of a prototype which a constructor reference set back to itself and a proto set to object?
No wonder there is confusion. The picture is misleading to the point of being incorrect!
Objects created by calling a constructor function with the new keyword have their inheritance chain set to start with the prototype property of the constructor (correct in the picture).
The prototype property is created every time a function is declared using the function keyword to cover the case of the function being use as a constructor later - so you don't need to specify if a function is a constructor or not. For completeness, functions generated by the class keyword also have a prototype property.)
The function's prototype property's constructor property is set to the function when the prototype property is created (meaning when the function is declared). Again the picture is correct: the value of Foo.prototype.constructor is a reference to Foo.
What is wrong in the picture is objects a and b somehow joining together in a reverse fork and their properties becoming available to instances of Foo.
constructor is always an inherited property. If you replace the original prototype property of a function object with another object, you replace the constructor property inherited by objects constructed with the function. Although you can reset the constructor property of a functions prototype property, it's reasonably unusual and not a part of the story the picture is presenting.
If you do modify the inheritance chain by changing a function's prototype property value, the inheritance chain is still always a single threaded chain back to Object.prototype and then null. The inheritance chain never forks as shown in the picture. If you modified Foo.prototype in the picture to make it a or b, the constructor property of Foo instances would not be Foo.
The picture requires a lot of explanation to be useful.
The properties are assigned in the construction function. Any function can be used with new,thus becoming the "construction function".
var f = function(){};
var fInstance = new f();
console.log(fInstance.constructor); // *f*
If there are no properties assigned in that function (using this.propertyName), then the constructed instance will not have properties. If it does, then it will.
// No properties
var f = function(){};
// Two constructor properties, and one default property
var f = function(prop1, prop2){
this.name = prop1;
this.description = prop2;
this.something = "default";
};
If the prototype of the construction function has properties or methods (basically just glorified properties) attached to its prototype, then each instance will have those.
// No prototype
var f = function(){};
// Prototype with one method
var f = function(){};
f.prototype.test = function(){ console.log("hello"); };
The prototypes and properties must be manually created, and may or may not exist. By default, since using new requires a function, there will always be a constructor function. The process of instantiation using new will also always assign the prototype of the constructor to an object containing the constructing function as a property named constructor as well as all of the properties/methods of the construction function's prototype.
In this case, foo is a constructor function and B and C are objects.
Functions are also objects. Everything are objects. unlike classical inheritance where what defined objects are separate entities. Here an object that is an instance of Function is the constructor that will create an instance of its kind that inherits whatever object is on the constructors prototype attribute.
I am very confused, first off when you create an object does it
always come with the properties and proto? Is that the default?
Only way to get the objects own property y is if the constructor function sets this.y. If a property is not found on the object the system will continue to look at the object that was on the constructors prototype field. Some implementations has this as __proto__ but that is not a requirement. It is implementation specific how it is stored on the instance.
Also in terms of the constructor function for foo. Am I correct to say
that every proto of a function defaults to Function.prototype, which
uses Object.prototype to create an object?
function() {...} makes an instance of the constructor Function. All objects except Object itself inherits Object either indirectly or directly, including Function. Basically you can make a function like this:
var f = new Function('a', 'b', 'return a + b');
f is an instance of Function, as you can see. This is almost the same as:
var f = function(a, b) { return a + b; };
Now the first allows for text to be interpreted as code so its less efficient, but I imagine that in the early days these two would be identical in terms of interpretation. Modern engines prefer the last one since it is more predictable while the first can be seen as a specialized eval.
The part that is confusing for me is Foo.prototype, when was this
prototype created? Does a constructor function always default to the
creation of a prototype which a constructor reference set back to
itself and a proto set to object?
Yes. When the function Foo is created, JS creates by default protoype as new Object(), then it sets constructor to itself. The rest needs to be done in the code itself so we know there is something like this after the actual function code to do the rest of the class:
Foo.prototype.x = 10;
Foo.prototype.calculate = function(...) {...};
One thing I don't understand with prototypes and constructor functions..
Say I have this constructor function that will create an object with a 'name' property and a 'logName' method
function MyExample(param1){
this.name = param1;
};
MyExample.prototype.logName = function(){
console.log(this.name);
}
I understand I just added a method (logName) to the constructor function's (myExample) prototype..so that when I create a new object (me) using this constructor function that object will inherit the 'name' property and the 'logName' method. The logName method will be part of new object's (me) proto property
var me = new MyExample('bob');
me.logName(); //bob
..But why not just add the logName method to the object the constructor function is creating? (not the prototype of the constructor function) Wouldn't that provide the same result? Even though 'logName' will not be part of the new object's proto property.
function MyExample(param1){
this.name = param1;
this.logName = function(){
console.log(this.name)
};
};
var me = new MyExample('bob');
me.logName(); //bob
In your second example you recreate the logName function every time you create a new instance of MyExample. If you use the MyExample's prototype then one logName method is shared across all instances of the MyExample object and context is passed around automatically.
The prototype also allows you to add a new method at a later point that can be accessed by already-existing objects of that type or globally modify a method for all objects of a type.
This question touches on the same topic if you would like more information, Advantages of using prototype, vs defining methods straight in the constructor?
The problem with creating the method in the constructor is that it isn't being shared among all instances of MyExample.
Instead, each MyExample has it's own copy of the function. It ends up taking up more memory as the number of instances goes up and if for some reason you want to modify all MyExamples at run time, you have to change every single instances function instead of modifying the prototype.
It's the difference between everyone looking at the same "copy" of Wikipedia versus everyone saving all of Wikipedia to their hard drive and reading that. It pointlessly uses up extra hard drive space and if Wikipedia is updated, everyone is wrong until they download the new version.
If for some reason you need a function which is very similar across instances but will be slightly different for each instance (for example, using closure variables) then creating methods in the constructor may be the right way to go.
Adding methods in the prototype gives your code better abstraction.
For example, since the methods are not tied to the instances, you are able to call them on non-instances which are compatible enough. Like this:
Array.prototype.slice.call({0:'a', 1:'b', length:2}); // ["a", "b"]
If you only defined your methods on the instances, it would be necessary to create an useless instance in order to borrow the method:
[].slice.call({0:'a', 1:'b', length:2}); // ["a", "b"]
Additionally, defining a method inside th constructor means that each instance will receive a different copy.
new MyExample('bob').logName === new MyExample('bob').logName // false
This means you will waste more memory.
I've been using code like this for inheriting from another object:
// define base object constructor
function SuperType(){
// constructor code
}
// define base object methods on the prototype
SuperType.prototype.foo = function() {};
// ---------------------------------------------------------------------------
// define object that wants to inherit from the SuperType object
function SubType() {
// call base object constructor with all arguments that might have been passed
SuperType.apply(this, arguments);
// other constructor code
}
// set prototype for this object to point to base object
// so we inherit any items set on the base object's prototype
SubType.prototype = new SuperType();
// reset constructor to point to this object not to SuperType
SubType.prototype.constructor = SubType;
// define any methods of this object by adding them to the prototype
SubType.prototype.myMethod = function() {};
My question is why do you have to set the SubType.constructor = SubType? When is the .constructor property actually used? If you create a SubType object like this:
var s = new SubType();
That's going to call the SubType() constructor regardless of what SubType.prototype.constructor is actually set to, so I'm trying to understand when the .constructor property is ever actually used?
As you can see in this jsFiddle demo with the assignment to .constructor commented out, the proper constructor is still called. So, it appears that the .constructor property is not used in normal construction with the new operator. I'm wondering when it is used?
According to the The ECMAScript Language Specification,
The initial value of Object.prototype.constructor is the standard built-in Object constructor.
In other words, it's just a pointer to the Object's actual, native constructor-- The one that is called via new Object(). Thus, you can override it without changing anything about how new Object() works.
So why does it exist? Because constructor functions are effectively classes in JavaScript, it lets you do certain things with class instances without needing to their class name. To borrow from Axel Rauschmayer's blog, the constructor property allows:
Comparing between classes, i.e. a.constructor === b.constructor
Creating a new instance from an existing instance, i.e. new a.constructor()
Invoking another (super)class's constructor
All without any hardcoded references to class names. Again, it's not really meant to be overridden. To echo the above comments, I've never really seen someone override it in the wild.
Which method below is best to define a constructor prototype and why?
Method 1:
MyConstructor.prototype.myFunction1 = function(){};
MyConstructor.prototype.myFunction2 = function(){};
Method 2:
MyConstructor.prototype = {
myFunction1: function(){},
myFunction2: function(){}
};
I'm mostly concerned about speed. Thanks!
I would say there wouldn't be much of a difference. Using an object literal to assign to the Object.prototype is something you can't do if you're assigning the prototype within the constructor (which can be usefull sometimes).
Maybe you should write a little performance test using jsperf.com.
var example = new MyConstructor();
under method 1:
example.constructor === MyConstructor;
under method 2:
typeof(example.constructor) === 'undefined';
The prototype object that comes with a function has a property constructor that points back to the function. If you assign to the proprties of that object, you keep the constructor property. If you overwrite the prototype property with a new object, you lose the constructor property.
The performance difference is minimal. Because constructor is so fragile, you can't really trust it, so I don't bother to preserve it.
You should use the method 1. Using the method 2, everytime you create a new instance, you will "re-create" the methods, since they are inside the constructor.
Speaking further about the readability of your code,
method 1 is better than method 2.
Method 2 spend one more indentation. So it cause difficulty for reading codes.
Additionally, in my case,
I can't inference that whether this function is prototype method or just static member function when we see a function name part in the lower part of codes.
Personally, in conclusion,
I prefer method 2 if there not be much of a difference about performance.
Thanks!