11

I'm new to prototyping and instantiations and therefore had a question :

  • How can I create a function that constructs a new array that also has some properties added with prototype but without modifying the default Array function ?

For example :

function Cool_Object() {
    this = new Array() // Construct new array.
    //This is only for the example. I know you can't do that.
}
Cool_Object.prototype.my_method = function() {
    // Some method added
};

So, if you call :

var myObject = new Cool_Object();

myObject would be an array and have a method called "my_method" (which actually calls a function).

But the default Array object would be intact.

Thanks in advance !

1

5 Answers 5

12

You've got it a bit backwards. Just use Array.prototype as your custom object's prototype.

function Cool_Object() {

    this.my_method = function () {
        return 42;
    }
}

Cool_Object.prototype = Array.prototype;

var foo = new Cool_Object();
foo.my_method(); // 42
foo.push(13);
foo[0]; // 13

You can get both Array.prototype and my_method on Cool_Object's prototype, without modifying Array.prototype, by introducing an intermediate type:

function Even_Cooler() {}
Even_Cooler.prototype = Array.prototype;

function Cool_Object() {}
Cool_Object.prototype = new Even_Cooler();

Cool_Object.prototype.my_method = function () {
    return 42;
}
Sign up to request clarification or add additional context in comments.

8 Comments

Oh, ok I understand what you meant now. Thank you both bfavaretoo and Matt Ball very much. I didn't knew that you could use Array.prototype like this !
Cool_Object.prototype = Array.prototype;: Then you should not extend Cool_Object.prototype though. Better: Cool_Object.prototype = Object.create(Array.prototype);.
I don't understand the difference. Can you explain it ? Other question, if you use a for ... in loop on Cool_Object, is it possible to not loop through the length and my_method properties ? Thanks !
@Felix King - Why not Cool_Object.prototype = [];? That's what I did in my answer - is it wrong?
Or should I just use a normal for(var i=0; i < this.length; i++) {} loop instead of "reading" properties like a for ... in loop ?
|
6

You can't just assign to this, it doesn't work and throws a ReferenceError. Just make Cool_Object extend Array.

One way to do that:

var Cool_Object = Object.create(Array.prototype);
Cool_Object.my_method = function() {
    // Some method added
};

Then create further objects with

var obj = Object.create(Cool_Object);

2 Comments

nice! can you explain how does array indexed properties actually defined in their prototype? what if we need only to have just this special behaviour (access to items by index) not all other methods defined in array prototype like as push, concat, join, reduce,...
If you need a length, it has to inherit from array. Otherwise you can use plain objects.
1

Use an array as the function's prototype, so that your new type "inherits" from Array, and then introduce new methods in the prototype:

function CustomArray() {}

CustomArray.prototype = [];

// introduce a new method to your custom array type
CustomArray.prototype.total = function() {
    return this.reduce(function(ret, el) {
        return ret+el;
    }, 0);
};

// introduce another new method to your custom array type
CustomArray.prototype.arithmetiMean = function() {
    return this.total()/this.length;
};

Alternately you could introduce those methods in new instances:

function CustomArray() {
    // introduce a new method to your custom array object
    this.total = function() {
        return this.reduce(function(ret, el) {
            return ret+el;
        }, 0);
    };

    // introduce another new method to your custom array object    
    this.arithmetiMean = function() {
        return this.total()/this.length;
    };
}

CustomArray.prototype = [];

var arr = new CustomArray();

arr.push(1); // push is an array-standard method
arr.push(2);
arr.push(3);
arr.push(4);
arr.push(5);
arr.push(6);
arr.push(7);
arr.push(8);
arr.push(9);
arr.push(10);

console.log(arr.arithmetiMean());

Comments

-1

Adding this for reference, since Object.create is supported in most browsers these days, a good way to make your own array object would be like this:

function MyCustomArray(){

}

MyCustomArray.prototype = $.extend(Object.create(Array.prototype), {
    /* example of creating own method */
    evenonly : function(){
        return this.filter(function(value){return (value % 2 == 0);});
    },

    /* example for overwriting existing method */
    push : function(value){
        console.log('Quit pushing me around!');

        return Array.prototype.push.call(this, value);
    }
});

var myca = new MyCustomArray();
myca instanceof MyCustomArray /*true*/
myca instanceof Array /*true*/
myca instanceof Object /*true*/
myca.push(1); /*Quit pushing me around!*/
myca.push(2); /*Quit pushing me around!*/
myca.push(3); /*Quit pushing me around!*/
myca.push(4); /*Quit pushing me around!*/
myca.push(5); /*Quit pushing me around!*/
myca.push(6); /*Quit pushing me around!*/

myca.length; /*6*/
myca.evenonly() /*[2, 4, 6]*/

Using jQuery's $.extend, because it's convenient to keep code structured, but there's no need for it, you could do this instead:

MyCustomArray.prototype = Object.create(Array.prototype);

MyCustomArray.prototype.push = function(){...}

I much prefer defining the methods on the prototype rather than putting them inside the constructor. It's cleaner and saves your custom array object from being cluttered with unnecessary functions.

1 Comment

Your length only has the expected value because you used push, not because myca is an array.
-1

function PseudoArray() {

};
PseudoArray.prototype = Object.defineProperties(Object.create(Array.prototype), {
	constructor: {value:PseudoArray}
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.