3

I've been trying to understand inheritance in Javascript and so far I've read many sites about that (including javascript.info and Crockford's Javascript Good parts) - yet I can't seem to understand something as simple as Array inheritance.

Maybe if I demonstrate with an example, somebody can correct me and teach me what I'm getting wrong.

function ExtendedArray() {
    Array.call(this, arguments);

    this.test = function () {
        return 'something';
    }
}

//I think this is the most standard way to extend a class?
ExtendedArray.prototype = [];
ExtendedArray.prototype.constructor = ExtendedArray;

$scope = {};

$scope.arr = new Array(1, 2, 3);
$scope.concatArr = [].concat($scope.arr);

$scope.x = new ExtendedArray(1, 2, 3);    //empty | instanceof Array = true
$scope.concatX = [].concat($scope.x);     //empty

$scope.y = new ExtendedArray();          //instanceof Array = true
$scope.y.push(1, 2, 3);                  //works - elements are added!
$scope.concatY = [].concat($scope.y);    //concats it like a object

Here is a JS-Fiddle for the same:

http://jsfiddle.net/superasn/pq2j139c/

Some questions:

  1. How do I fix this code so that ExtendedArray behaves as Array?
  2. As you can see $scope.x is empty. Why is the constructor not working?
  3. The push functions works!? But then concat fails? How to make concat work?
  4. I see there are some libraries to extend Classes, is that a better approach to JS inheritance?

Your advise is appreciated!

5
  • 1
    [].concat($scope.x) is not empty, it contains one instance of an ExtendedArray object Commented Apr 30, 2015 at 11:47
  • 2
    I just found this article from this question - seems relevant Commented Apr 30, 2015 at 11:51
  • Thanks.. Yes, i too found that perfectionkills article yesterday and it only added to my confusion. I stopped reading when things started getting into weird territory with him using Iframes for something as simple as array inheritance.. i'll give it another go today. Commented Apr 30, 2015 at 11:55
  • I'm not surprised, it is long-winded and non-trivial. You might want to just look at the Naive Approach which seems to be equivalent to what you're attempting to achieve Commented Apr 30, 2015 at 11:56
  • You are right.. I modified my fiddle and it seems to be working.. jsfiddle.net/superasn/9ykr1gbn Now to fix the concat thing and understand inheritance better (p.s. sorry i shouldn't post so frequently but i'm pretty excited to see it working) Commented Apr 30, 2015 at 12:03

1 Answer 1

0

You just must call [].push.apply(this, arguments); in constructor:

angular.module('myApp', [])
.controller('mainCtrl', ['$scope', function($scope) {

    var __extends = this.__extends || function (d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
                function __() { this.constructor = d; }
                __.prototype = b.prototype;
                d.prototype = new __();
            };
    
    function ExtendedArray() {
        Array.call(this, arguments);
        
        [].push.apply(this, arguments);
        
        this.test = function () {
            return 'something';
        }
    }
    
    __extends(ExtendedArray, Array);

    $scope.arr = new Array(1, 2, 3);
    $scope.concatArr = [].concat($scope.arr);
    
    $scope.x = new ExtendedArray(1, 2, 3);    
    $scope.concatX = [].concat($scope.x);
    
    $scope.y = new ExtendedArray();    
    $scope.y.push(1, 2, 3);
    $scope.concatY = [].concat($scope.y);
    
    $scope.isArray = function(v) {
        return v instanceof Array;
    }
    
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="mainCtrl">
   <div class="content">
       Arr: Val = {{arr}} / Concat = {{concatArr}} / Is Array? {{isArray(arr)}}
       
       <hr/>

       X: Val = {{x}} / Concat = {{concatX}} / Is Array? {{isArray(x)}}

       <hr/>

       Y: Val = {{y}} / Concat = {{concatY}} / Is Array? {{isArray(y)}}
       
    </div>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

thanks! part 1 is working! now two quick questions, what the use of calling Array.call(this, arguments); if we have to push the arguments. Secondly, concat is still not working. It still thinks of it as one item.. how do I make concat work the way it works on a normal array?
Array.call(this, arguments); is doing absolutely nothing. You should remove it.

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.