-1

If I call myRobot.Speak.sayHi() it always returns undefined. Please, what am I doing wrong? Thanks for reply!

var Factory = (function() {

    // Constructor  
    var Robot = function() {

    };

    // Public
    return {
        extendRobot: function(power, methods) {
            Robot.prototype[power] = methods;
        },
        createRobot: function() {
            return new Robot();
        }
    };

}());

Factory.extendRobot('Speak', {
    sayHi: function() {
        return 'Hi, ' + this.name;
    }
});

var myRobot = Factory.createRobot();
myRobot.name = 'Robin';
myRobot.Speak.sayHi() // => ‘Hi, Robin’
2
  • You don't return anything so the method returns undefined. That's not a problem at all in this case. Commented Jun 4, 2011 at 0:17
  • @ThiefMaster Fixed... Still the same. Commented Jun 4, 2011 at 0:19

3 Answers 3

2
createRobot: function() {
    var r = new Robot();
    for (var k in r.Speak) {
        if (typeof r.Speak[k] === "function") {
            r.Speak[k] = r.speak[k].bind(r);
        }
    }
    return r;
}

Rather then returning a new robot, make sure to bind all the methods in your powers to the robot.

To avoid hard coding in the loops try this:

Robot.powers = [];
...
extendRobot: function(power, methods) {
    Robot.powers.push(power);
    Robot.prototype[power] = methods;
},
createRobot: function() {
    var robot = new Robot();
    Robot.powers.forEach(function(power) {
        for (var method in robot[power]) {
            if (typeof robot[power][method] === "function") {
                robot[power][method] = robot[power][method].bind(robot);
            }
        }
    });
    return robot;
}

This relies on Function.prototype.bind so use the ES5 shim or use underscore for supporting old browsers (IE<9)

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

Comments

2

myRobot.Speak.name = 'Robin';

In your case, this refers to Robot.Speak, not the parent object Robot.

3 Comments

Thanks for reply! Should I use apply or call?
But... I would like to access variable myRobot.name from myRobot.Speak.sayHi. :-| Is it even possible?
@Emmitt: Yes, it's possible, but it may make your code a little more complex.
0

insert name : this.name before the line sayHi: function() { and then it should work

2 Comments

No it won't, because this.name will refer to Factory.name when calling Factory.extendRobot
@chomp: No, it won't; it will refer to window.name.

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.