'Is returning "this" in a function a recommended pattern to create objects with methods?

I find myself sometimes needing this pattern in some specific situations but I don't often see it when reading code. I was wondering if this is a recommended pattern or if there's a better/more common way of accomplishing the same thing. Maybe a more modern way to do the same thing in ES6?

Example:

const state = {}
const stubs = {}
const query = () => {

    stubs.collection = sinon.stub().callsFake( (collection) => {
        state.collection = collection
        return this
    })
    stubs.orderBy = sinon.stub().callsFake( (orderBy, direction) => {
        state.orderBy = orderBy
        state.direction = direction
        return this
    })
    stubs.limit = sinon.stub().callsFake( (limit) => {
        state.limit = limit
        return this
    })
    stubs.get = sinon.stub().callsFake( () => {
        const query = state 
        state = {}
        const data = getQuery(query, mockDb)
        return data
    })

    this.collection = stubs.collection
    this.orderBy = stubs.orderBy
    this.limit = stubs.limit
    this.get = stubs.get
    return this
}
stubs.firestore = sinon.stub(firebase, 'firestore').get( () => query )

Basically the reason I'm using it in this situation is I had to stub a "query" method for firebase unit tests. It had to work in a chain like this firebase.firestore().collection('users').orderBy('timestamp').limit(10).get(). I messed around with it for like 5 hours and couldn't find another way that worked.

An example without the stubs part would be:

const query = () => {

    this.collection = () => {/*something...*/ return this}
    this.orderBy = () => {/*something...*/ return this}
    this.limit = () => {/*something...*/ return this}
    this.get = () => {/*something...*/ return this}
    return this
}

I'm not sure why I would actually need to write something like this if I didn't need stubbing, it's just an example to make it more clear what I'm talking about without the stubs part.



Solution 1:[1]

The better way:

const query = () => {
    return {
        collection() => { /* Code */ }
        orderBy() => { /* Code */ }
        limit() => { /* Code */ }
        get() => { /* Code */ }
    }
}

In this way, instead of writing the methods to this and returning this while mutating it (maybe, in a browser, this === window, in non-strict mode), you can directly return an object containing those methods, and the this used inside those method gives the object which is being returned by the query function.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1