David Alan Condit
David Alan Condit

Reputation: 1253

Returning a getter, defined on an object literal?

Please take a look at how function Y "reuses" function X's itemCount getter. I thought I should be able to define it as itemCount: x.ItemCount, but that doesn't work.

Question: Can someone explain why I have to do the below to return X's itemCount from Y? There must be something that makes get special from a normal function.

// Returns simple object literal with 2 properties.
function X () {
    return {
        items: {
            1: {},
            2: {}
        },
        get itemCount () {
            return Object.keys(this.items).length;
        }
    }
}

// Returns a simple object literal with the same 2 properties as its "x" arg.
function Y (x) {
    return {
        items: x.items,
        get itemCount () {
            return x.itemCount;
        }
    };
}

var x = new X();
var y = new Y(x);
y.itemCount; // returns 2

Upvotes: 1

Views: 103

Answers (2)

Ryan Searle
Ryan Searle

Reputation: 1627

If you used a function instead of a getter you would have to bind the value of this.

For example like this:

function X () {
    return {
        items: {
            1: {},
            2: {}
        },
        itemCount: function() {
            return Object.keys(this.items).length;
        }
    }
}

function Y (x) {
    return {
        items: x.items,
        itemCount: x.itemCount.bind(x)
    };
}

When you call x.itemCount() the value of this is in the context of x however if you call y.itemCount() (y being the object created from Y(x)) this will be in the context of y.

In order to get around this you need to bind the this variable using bind().

Upvotes: 1

apsillers
apsillers

Reputation: 115910

You're running the code return x.itemCount. It is expected, therefore, that value returned by that return statement is the computed value of the itemCount property on x -- what else could x.itemCount possibly be?

If you want to run the code of the itemCount getter on a different object, the best course is to extract out the item-counting code into a separate function that is used by the getter:

function itemCounter(obj) {
    return Object.keys(obj.items).length
}

Then each itemCount getter can return itemCounter(this).

If you don't have the ability to modify x, you can inelegantly extract the getter and call it with the this of y:

Object.getOwnPropertyDescriptor(x, "itemCount").get.call(this)

Upvotes: 0

Related Questions