0

I really tried hard to find very simple and working example (e.g. on MDN), but it makes me mad. I can not simply figure out, where I do mistake. I would like to have an ancestor of the Array object. Here is sample.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Fiddling</title>
<script>


function Synthese() {
    //Array.call(this); 
    //Synthese.prototype = Object.create(Array.prototype);
    //Synthese.prototype.constructor = Synthese;

    this.prototype = Object.create(Array);
    //this.prototype.constructor = this;
    this.Make = function () {
        result = "";
        for (i=0; i<this.length; i++){
        result = result + this[i] + ".";    
        }   
        return result;
    }
}
var A = new Array();
A.push("A"); //OK
var S = new Synthese();
S.push("A"); //fails
S.push("B");
alert(S.Make());
</script>
</head>
<body>
</body>
</html>

How make Synthese be child of Array? S.push("A"); never executes

lyborko
  • 2,571
  • 3
  • 26
  • 54

2 Answers2

3

You can't correctly inherit from Array in ES5 or earlier. It's one of the few limitations of the inheritance mechanism.

That was fixed in ES2015 (aka ES6), via the new class keyword:

// ES2015 and above only
class Synthese extends Array {
}

This feature cannot be shimmed/polyfilled by transpilers like Babel (because you can't do it in ES5, you need a feature the JavaScript engine deosn't have until ES2015).


Unrelated to the Array problem, your pattern of implementing a derived constructor function isn't quite right. I've written a thorough explanation and example in this answer if you still need to do this in ES5 and aren't using a transpiler.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • What does it mean, that you can not correctly inherit from Array? – lyborko Feb 28 '16 at 17:24
  • @lyborko: It means exactly that: You can't correctly inherit from `Array` (in ES5 and earlier). It just can't be done. `Array` objects have a couple of quite special behaviors (primarily the `length` property) that simply don't work correctly if you try to create something inheriting from `Array` in ES5 and earlier. It required changes in the language specification and JavaScript engines to make it possible in ES2015. – T.J. Crowder Feb 28 '16 at 17:35
  • thank you for the explanation. So I will do work around. Hopefully instantiate Array inside object constructor would be possibly correct. Like: this.Arr = new Array(); and then somewhere in the code Synthese.Arr.push("A"); – lyborko Feb 28 '16 at 18:10
  • @lyborko: Yeah, that's usually what we end up needing to do. BTW, `= new Array()` is never necessary unless you're specifying a length (passing a number into it), just `= []` is more concise. – T.J. Crowder Feb 28 '16 at 18:11
0

You should set prototype after constructor

..
    function Synthese() {
        //Array.call(this); 
        //Synthese.prototype = Object.create(Array.prototype);
        //Synthese.prototype.constructor = Synthese;

        this.prototype = Object.create(Array);
        //this.prototype.constructor = this;
        this.Make = function () {
            result = "";
            for (i=0; i<this.length; i++){
            result = result + this[i] + ".";    
            }   
            return result;
        }
    }
    Synthese.prototype = []; // HERE
    var A = new Array();
    A.push("A");
    console.log(Object.getPrototypeOf(S));
    S.push("A");
    S.push("B");
    alert(S.Make());
..
Slava N.
  • 596
  • 4
  • 6
  • I made a fiddle, just run it https://jsfiddle.net/nikishkinvv/4v3r4acs/ . This produces result "A.B.". It isn't right? – Slava N. Feb 28 '16 at 16:48
  • it is right.... unbelievable... :-). Why I have to declare prototype outside object constructor remain mystery for me... Weird. I have to think about it... Anyway, your answer is correct, so somebody could answer, why it is down voted. Thanx a lot. – lyborko Feb 28 '16 at 17:02
  • @lyborko: This answer is not correct, in a couple of different ways. First, again, you just cannot "subclass" `Array` in ES5 and earlier. Can't be done. Secondly, this is creating a property called `prototype` on the instance created by `new Synthese`, which makes no sense. It also drops the line defining and initializing `S` but then attempts to take the prototype of `S`. It also retains some errors from your original code that shouldn't appear in an answer supposedly telling you how to do something, primarily The Horror of Implicit Globals (declare your variables). In short: Not useful. – T.J. Crowder Feb 28 '16 at 17:39
  • @T.J.Crowder: yes, you are right; anyway I corrected the code, it "works", but keeping in mind, what you say, I will never do it this way... I have also read your other article, but it is not so easy to absorb whole stuff abruptly. I was doing much in Delphi, but here in javascript I feel a little bit confused... Thanks. – lyborko Feb 28 '16 at 18:17