0
function Base(x) {
    this.x = x;
    this.sub = new (function Sub() {
        this.method = function() {
           return function() {**this.super.x**}; // return an anonymous function that uses the outer x, but for reasons the anonymous function can't take parameters
        }
    });
}

var base = new Base(5);
console.log(base.sub.method()())

basically, in this example I'm trying to create an object Base who has a sub object sub, which has a 'method' that uses an anonymous function. The anonymous function needs the x but cannot take in any parameters.. Is there any way to access the this.x of Base?

At the beginning I tried the following. This works well when Base is not inherited by other objects. But in the following

"use strict";

function Base(x) {
    var that = this;
    this.sub = new (function Sub() {
        this.method = function() {
           return function() {
                console.log(that); // displays Base *note[1] 
                return that.x;
           }; // return an anonymous function that uses the outer x, but for reasons the anonymous function can't take parameters
        }
    });
}


function Other() {
    Base.call(this); // why do I need to call Base.call(this) ?
    this.setX = function(x) {this.x = x;}
}
Other.prototype = new Base();
var other = new Other();

other.setX(5);
console.log(other.sub.method()()); // otherwise undefined?

Base is extended by Other, after struggles I figured out I need to call Base.call(this); in order to make it works. Otherwise console.log(other.sub.method()()); will be undefined.

If I put a console.log(that) at *note[1], it will actually says the that is a Base object even though I construct it using var other = new Other(); I guess the problem would be solved if that is an Other object? What am I misunderstanding here?

My question is why do I need to call Base.call(this)? Why does it works after calling it? Is there any better solution to this situation?

Larry
  • 858
  • 10
  • 16

2 Answers2

1

If I understand you correctly you'd like Base to have a Sub and Sub is aware of the Base instance?

At the moment you're declaring the Sub type over and over again every time you create a Base, not the most effective way of doing it. Maybe try something like this:

function Sub(baseInstance){
  this.baseInstance = baseInstance;
}
Sub.prototype.displayBaseX=function(){
  console.log('base.x in sub:', this.baseInstance.x);
};
function Base(){
  this.x = 22;
  this.sub = new Sub(this);
}

You should not create an instance of Parent to set prototype of Child, use Object.create instead.

As for Parent.call(this, arguments) that is to re use the constructor function of Parent in Child when inheriting. More info about that can be found here: https://stackoverflow.com/a/16063711/1641941

The reason why your code doesn't work without Base.call(this); is because Base constructor defines and creates it's Sub type and instance. Not re using the Base constructor code when creating a Other type would cause the Other type not to have a Sub instance.

Constructor code deals with instance specific members and prototype can hold members that are shared by all instances. So usually behavior (functions) and a value for immutable default data members (numbers, string, boolean) can be found on the prototype.

Community
  • 1
  • 1
HMR
  • 37,593
  • 24
  • 91
  • 160
  • thank you for the help :> `At the moment you're declaring the Sub type over and over again every time you create a Base` does this mean that for a normal type, I shouldn't define methods inside the constructor, instead, I should define them using the prototypes? – Larry Nov 03 '14 at 05:46
  • As for this particular question, my Base type is a singleton so I only need to declare it once. Do you mean `Type_name.prototype.function_name=functon(){}` is more efficient than declaring methods inside the constructor? Or is it only the case that I shouldn't declare another type inside a type? – Larry Nov 03 '14 at 05:50
  • @Larry you are creating Base types every time you create Other type because that inherits from Base and calls it's constructor (Base) every time you create an instance of Other. In the following answer that is demonstrated: http://stackoverflow.com/a/26696149/1641941 Did you read the constructor function introduction, inheritance and prototype (link in my answer)? Defining methods inside the constructor is sometimes done to simulate privileged methods (methods that have access to instance specific private members) but I don't use that pattern myself and it uses more resources. – HMR Nov 03 '14 at 09:13
1

I'm not exactly sure what you're end goal is here. But to solve your scope issue, this seems to work.

"use strict";

function Base(x) {
    this.sub = new (function Sub(_this) {
        this.method = (function(_this) {
           return function() {
                return _this.x;
           };
        })(_this);
    })(this);
}


function Other() {
    Base.call(this); // why do I need to call Base.call(this) ?
    this.setX = function(x) {this.x = x;}
}
Other.prototype = new Base();
var other = new Other();

other.setX(5);
console.log(other.sub.method()); // otherwise undefined?

And a fiddle.

EvilZebra
  • 1,072
  • 8
  • 18
  • Why would you define the type Sub inside Base? Your type definition part gets executed every time you create a Base instance. – HMR Nov 03 '14 at 04:53
  • 1
    Like I said, I don't understand why he wants the code to work the way described. Just offering a solution. – EvilZebra Nov 03 '14 at 04:55