0

My question is related to JavaScript Inheritance,

var a = new Array();
var b = new Array();

a.prototype.max = function () {
 alert("Max");
}

b.max();

As per my understanding b.max() will give error saying b doesn't have max , but surprisingly(for me) it gives me error at 3rd line a doesn't have prototype. when I do typeof a its gives me Object, object can have prototype property.I read JavaScript follow prototype inheritance,i.e. instance based inheritance, so my question is I have created an instance of Array, still prototype property is not define.

Could you please explain me where I am going wrong, or what concept I've not understood properly

Yashprit
  • 512
  • 1
  • 8
  • 22
  • But you have no constructor... Maybe you want `Array.prototype.max`? – elclanrs Nov 13 '13 at 05:03
  • I think this will help you http://stackoverflow.com/questions/650764/how-does-proto-differ-from-constructor-prototype –  Nov 13 '13 at 05:04
  • you have to do Array.prototype.max – om_deshpande Nov 13 '13 at 05:05
  • prototype is where shared members are. Setting or changing it through an instance isn't good practice. Adding to Array.prototype isn't a good idea either. http://bolinfest.com/javascript/inheritance.php under "The Google Maps team learned this the hard way" All about constructor functions and prototype: http://stackoverflow.com/a/16063711/1641941 – HMR Nov 13 '13 at 05:13

5 Answers5

0

prototype belongs to function object, not every object.

So Array.prototype is right, a.prototype is wrong.

xdazz
  • 158,678
  • 38
  • 247
  • 274
0

It should be like this:

var a = new Array();
var b = new Array();

Array.prototype.max = function () {
 alert("Max");
}

b.max();
Ankit Tyagi
  • 2,381
  • 10
  • 19
0
> var a = new Array();

a is an instance of an Array object, only Function objects have a prototype property by default. All objects have a hidden [[Prototype]] property that you can't access (other than through the non–standard __proto__ property) and references their constructor's prototype at the time they are constructed (or as otherwise modified via __proto__).

So when attempting to resolve:

a.prototype.max 

then

a.prototype

is undefined so attempting to get the max property of undefined throws a reference error.

b is also an instance of Array, it doesn't have a max property. Even if you do:

a.prototype = {max: function(){});

b will still not have a max property since it inherits from Array.prototype, not a.prototype.

PS. See ECMA-262 §15.3.2.1: "A prototype property is automatically created for every function, to provide for the possibility that the function will be used as a constructor.".

RobG
  • 142,382
  • 31
  • 172
  • 209
  • Thanks detailed answer. concept here is its belong to Functional Object not every object, I didn't knew this, good learning – Yashprit Nov 13 '13 at 05:26
0

It's better not to extend things like Array, especially when you write a library or expect your code to be re used by many other programs.

Object.prototype.somethingElse=22;
Array.prototype.something=22;
var arr=[1];
for(thing in arr){
  console.log(thing);//0, something,somethingElse
};

Besides this problem your code may be used with libraries that have a conflicting implementation of Array.prototype.max.

From an Iframe or Frame the max function doesn't exist because Array in an (i)frame is not the same as the Array on the main page.

Instead write a function that you can call or pass the array as an extra argument:

function max(){
  console.log(this);//<=[1,2]
  return Math.max.apply(Math,this);
};
var arr = [1,2];
max.call(arr);//=2
HMR
  • 37,593
  • 24
  • 91
  • 160
  • Agreed, you should never modify native class prototypes if they are expected to run alongside 3rd party code. – Aaren Cordova Nov 13 '13 at 06:53
  • Yes, that's correct but my question was if its a instance based inheritance, than why a.prototype is not working, which I understood, prototype is only work in case of functional Object not instance. But thanks for giving above advice. – Yashprit Nov 13 '13 at 08:00
  • @yashprit I see, in that case you can do: `a.max=function(){console.log("it's max")};` – HMR Nov 13 '13 at 08:53
  • @HMR Yes, that's work fine, because its comes from the fact that we can providing property to the object, because at the end everything is object, having said that I was wondering why prototype is not available to these kind of object, because we do same thing with prototype. What make difference with these two approaches ? – Yashprit Nov 13 '13 at 09:14
  • @HMR, see this :- var MyArray = function () { return new Array(); } MyArray.prototype.max = function () { alert("I am max") } var a = new MyArray(); a.max = function () { alert("I am max override") } var b = new MyArray(); b.max() //max is undefined a.max(); – Yashprit Nov 13 '13 at 09:20
  • 1
    @yashprit b and a are Array, not MyArray. When you return an Object in a constructor function (as you do) then your a and b variables are assigned to that Object. If you were to return a primitive value (string, number or boolean) then a and b would be of type MyArray. Constructor functions do now have to return a value. – HMR Nov 13 '13 at 11:09
  • 1
    @yashprit You're welcome, hope that learning more and more would make it more enjoyable to create programs (after scratching head and maybe some banging head against the desk time). – HMR Nov 14 '13 at 07:41
0

The prototype property is defined on the function object itself, not the instance. You could technically update the Array.prototype with you max function but then all Arrays in the current frame (past and present) will have the 'max' method. It is frowned upon to modify the prototype of native classes if you expect to work alongside 3rd party JavaScript. If you would like to inherit from the native Array class, you can use the simple inherits function listed below and call the parent class constructor. For a more detailed explanation on why this method of inheritance is preferred over others, please check out this post on how the inherits function works

function inherits(childConstructor, parentConstructor){
    var TempConstructor = function(){};
    TempConstructor.prototype = parentConstructor.prototype; // Inherit parent prototype chain

    childConstructor.prototype = new TempConstructor(); // Create buffer object to prevent assignments directly to parent prototype reference.
    childConstructor.prototype.constructor = childConstructor; // Reset the constructor property back the the child constructor (currently set to TempConstructor )
};

var CustomArray = function(){
    // Normally the below line would suffice, but the native Array class is overloaded in that a cast (or call) returns a new array instance.
    //Array.apply(this, arguments);

    this.push.apply(this, arguments); // This will achive what we originally wanted from `Array.apply(this, arguments);`
}
inherits(CustomArray, Array);

CustomArray.prototype.max = function(){
    var length = this.length;

    if(!length){
        return;
    }

    var maxValue = this[0];

    for(var i = 1; i < length; ++i){
        var value = this[i];

        if(value > maxValue){
            maxValue = value;
        }
    }

    return maxValue;
}




var nativeArray0 = new Array();
var nativeArray1 = new Array(1, 3, 4, 9, 5, 0, 7, 11, 2);

var customArray0 = new CustomArray();
var customArray1 = new CustomArray('c', 'a', 'd', 'b', 'f', 'y', 'g', 'p');

alert('customArray0.max() = ' + customArray0.max());  // undefined
alert('customArray1.max() = ' + customArray1.max());  // y
alert('CustomArray.prototype.max.call(nativeArray1) = ' + CustomArray.prototype.max.call(nativeArray1)); // 11

alert('nativeArray0.length = ' + nativeArray0.length); // 0
alert('nativeArray1.length = ' + nativeArray1.length); // 9
alert('nativeArray1[3] = ' + nativeArray1[3]); // 9

alert('customArray0.length = ' + customArray0.length); // 0
alert('customArray1.length = ' + customArray1.length); // 8
alert('customArray1[3] = ' + customArray1[3]); // b
Community
  • 1
  • 1
Aaren Cordova
  • 2,068
  • 1
  • 14
  • 7