BehnUm
BehnUm

Reputation: 141

Understanding Methods Chaining in Javascript

I'm new to ES6 and Javascript and I can't figure out what's wrong with chaining this dump() method in the following piece of code.

It returns "main.js:25 Uncaught TypeError: Cannot read property 'dump' of undefined":

class TaskCollection {

constructor(tasks = []) {
    this.tasks = tasks;
}

addTasks(newTasks = []) {
    this.tasks = this.tasks.concat(newTasks);
}

dump() {
    console.log(this.tasks);
}

}

let myTasks = new TaskCollection([
        'Do stuff'
]);

myTasks.addTasks([
    'New Task'
]).dump();

Now if I don't chain that dump() method, everything would work just fine.

myTasks.addTasks([
'New Task'
]);

myTasks.dump();

Upvotes: 4

Views: 90

Answers (3)

Vladu Ionut
Vladu Ionut

Reputation: 8193

You should return this in *addTasks* method

    class TaskCollection {
        
        constructor(tasks = []) {
            this.tasks = tasks;
        }
        
        addTasks(newTasks = []) {
            this.tasks = this.tasks.concat(newTasks);
            return this;
        }
        
        dump() {
            console.log(this.tasks);
        }
        
        }
        
        let myTasks = new TaskCollection([
                'Do stuff'
        ]);
        
        myTasks.addTasks([
            'New Task'
        ]).dump();

Upvotes: 2

Mjh
Mjh

Reputation: 2945

Method addTasks is not returning a reference to the object. If you want chaining to work, your method needs to look like this:

addTasks(newTasks = []) {
    this.tasks = this.tasks.concat(newTasks);

    return this;
}

Upvotes: 5

T.J. Crowder
T.J. Crowder

Reputation: 1074238

In order to use method chaining, you need to return this from the earlier method. In your case, you don't return this from addTasks, so the result of calling addTasks is undefined, and you can't call methods on undefined.

So just add

return this;

...to any method you want to be able to chain from.

Method chaining is not something special. When you do:

addTasks(/*...*/).dump();

what you're doing is effectively:

var x = addTasks(/*...*/);
x.dump();

...just without the variable. Depending on how addTasks is written, you might be calling dump on the same object (method chaining) or on some other object entirely (if addTasks returned something other than this).

Upvotes: 2

Related Questions