Total begginer who learns JS here. I don't understand why when you declare a variable it doesn't TOTALLY inherit of it's parent class methods, for e.g.:
// I initiate an array (my question is the same for all type of vars)
var myArr = ["foo", "bar"]
// Let's say I call a random function of the parent class Array
console.log(Array.isArray(myArr)); // true
// Since I assume that myArr inherited of the COMPLETE LIST of Array's methods, I should be able to do this:
console.log(myArr.isArray()); // Uncaught TypeError
Why don't the variables inherit of all of the methods of it's parent classes? Instead of that you need to mix between the fonctions of Array and myArr. They should be identitical on the two sides, no?
Array.isArray can also be called on non-arrays, so calling it from the instance of other classes would not have the method, resulting in a runtime error. Basically if you knew it was an array and it would be callable, you would not need to call it.
That is why it is NOT on the Array prototype and NOT callable from the instance.
const a = null
a.isArray() // bad
Array.isArray(a) // good
Developers have the option in Javascript to add methods to the class, the instance (aka prototype), or both. In this case it was only added to the class, not the instance.
It could have been added to the prototype of Object, but then it still would not be on the instances of boolean, number, string, symbol, or undefined.
When you declare a variable it is an instance of a Class, there is not inheritance.
When you declare a class that extends another class is where inheritance occurs.
Array.isArray() is a static property of the JavaScript Array object.
Usually, static methods are used to implement functions that belong to the class, but not to any particular object of it.
You need to pass an array as a parameter to the isArray function.Eg:
console.log(myArr.isArray(myArr))
Related
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.
In the code below I am trying to understand the behavior of the method assigned to the prototype object and those defined at the object definition of the function Vehicle:
function Vehicle(theMake) {
var make = theMake;
//this. attachs "make" to this instance of
//the object Vehicle which is infact an object of type Object
this.getInfo = function () {
return 'Local definition of getInfo, Vehicle: ' + make;
};
}
Vehicle.prototype.getInfo = function () {
//prototype will not have access to the variable make
return 'Overriding getInfo for all instances of Vehicle';// which later I realized is just the opposite( check the selected answer)
}
var car1 = new Vehicle('Honda');
alert(car1.getInfo());//Displays: Local definition of getInfo, Vehicle: Honda
1- Despite providing the definition of Vahicle.prototype.getInfo(), why the car1.getInfo() will be invoked? ( the local copy not the generic one?) why it ie being ignored?
If i remove the "this.getInfo = function()..."
then the generic getInfo will be invoked by car1.getInfo()
2-How can I invoke the car1.prototype.getInfo())? If I call it like car1.prototype.getInfo().call
the interpreter says: Unable to get property 'getInfo' of undefined or null reference
You should be assigning getInfo in only one place. Either in the prototype or in the constructor (preferably prototype), but NOT both places.
If you do both, the one assigned in the constructor will take precedence because it is assigned to the actual object which is searched first (before the prototype is searched). The prototype is only used if there is no property with the desired name already attached directly to the object. Because you've assigned a .getInfo property directly to the object in the constructor, the prototype is not searched when resolving that property name (because it's already found).
Since your code indicates that you think the .prototype version is the override, it appears that you just have that logic backwards. The getInfo() assigned to the object in the constructor is what overrides the prototype.
If you truly wanted to execute the prototype version, you could access it directly on the prototype:
Vehicle.prototope.getInfo.call(car1);
But, really if you want access to both methods, you should just given them different names so they are both accessible as car1.method1() and car1.method2().
So to summarize from your specific questions:
1- Despite providing the definition of Vahicle.prototype.getInfo(),
why the car1.getInfo() will be invoked? ( the local copy not the
generic one?) why it ie being ignored?
The object itself is searched before the prototype so the getInfo assigned directly to the object in the constructor will be found by the interpreter first and the prototype will not be searched.
2-How can I invoke the car1.prototype.getInfo())? If I call it like
car1.prototype.getInfo().call the interpreter says: Unable to get
property 'getInfo' of undefined or null reference
The best solution is to give the two functions different names so they are both callable in the conventional way. If you absolutely have to call the prototype version, you can do so as Vehicle.prototope.getInfo.call(car1);.
One might ask, why are you giving these two functions the same property name? That's what is creating the problem in the first place.
The prototype chain allows the object to delegate to it's prototype when there is a failed lookup on the constructor. You have provided an instance where there will not be a failed lookup, so there is no need for it to look up the method on the prototype.
I've seen some people add methods to the object class like so:
Object.clone = function() {
}
Is this syntax just like any other function name only with a period or is this actually adding to the Object class? Is this the same as a prototype method? What would be the pros/cons of doing this (or using a prototype) versus just making a function clone?
In JavaScript everything is an object this means that you can attach properties to any object, just like you would with an object literal, for example:
var arr = [1,2,3];
arr.property = 'foo';
It is not good practice to do so on non-objects though.
Every object has a constructor, so an array has an Array constructor, an object has an Object contructor, etc. The prototype of an object is an object whose context is the instance, this happens on custom objects when you instantiate with new.
When you attach a method to the prototype it will be shared across all instances of that object. When you attach a function to the constructor, you're basically hiding a global (depending on the scope) under a namespace; the context is not the instance, and it doesn't depend on one. You could think of these functions as static methods.
Extending Object.prototype is troublesome, since this is the "mother object". Extending the Object constructor itself isn't as bad, but not the best practice. The best solution, just create your own namespace:
var MY = {};
MY.clone = function(){};
There's no need to add static functions to the built-in Object constructor. There are also issues with code robustness if you do this, as some current and future environments may introduce built-in methods of the same name and then you have name collisions.
Just add your methods to your own objects.
I'm experimenting with the Google closure library and in particluar its 'inherits' method.
I have one question. When I extend a base class, if I do not set the base class's properties in its constructor, all the children end up sharing the properties, for example, if I add items to an array the array just keeps getting bigger.
Could someone explain why I need to set the properties in the constructor?
Here's my example, if you comment out "this.list = [9,8,7];" in the 'Person' constructor, the children share the persons list and keep adding to it.
http://jsbin.com/imujoy/1/edit
Thanks for any help.
When you reference "this.list" from the child, it first looks at the object itself to find that property. When it cannot find it, it looks at its prototype and finds the "list" array. That list, however, is a reference to the same list you created on the prototype of the Person. If you assign a new "this.list" in the constructor, you are just assigning a property on the object rather than the prototype. Generally speaking, you should not assign non-primitive types (Arrays, Objects) on the prototype if you intend to use an inheritance model because the children will share the same reference.
Are you copying parent defined variables in the child using Parent.call(this) or Parent.apply
function Child(){
Parent.apply(this,arguments);
}
goog.inherits(Child, Parent);
list becomes a property of any Child instance when defined in the Parent in the following manner:
function Parent(){
this.list=[];
}
Basic prototype behavior:
Prototypical inheritance - writing up
Good reference dealing with constructor parameters but to apply you have to implement _init and change goog.base:
How to "properly" create a custom object in JavaScript?
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.