Difference between Ember.get() and this.get()

Welcome to Ember 😉

Every object that extends Ember Observable mixin supports the get() method (among others).

When you call this.get(), the this must refer to such an object (Route, Controller, Component, your own class that extends Ember.Object and so on). Calling get() on plain object would cause a failure. Let me show the difference:

const emberObjectInstance = Ember.Object.create({
 name: 'Bala'
});

emberObjectInstance.get('name'); // returns 'Bala'

const plainObject = { name: 'Bala'};
plainObject.get('name'); // causes a failure since get() is not a function

However, using Ember.get() successes in both cases:

Ember.get(emberObjectInstance, 'name'); // returns 'Bala'
Ember.get(plainObject, 'name');         // returns 'Bala', too

which can be also written with imports as follows

import { get } from '@ember/object';

get(emberObjectInstance, 'name'); // returns 'Bala'
get(plainObject, 'name');         // returns 'Bala', too

Note: not to forget, calling either of get() makes computed property get computed (in the most common cases, I don’t want to dive deep now – lazy computation, volatile extensions etc), but for the sake of understanding the difference, we can work with plain values.

From own experience, I am using Ember.get() everywhere I know a plain object might be the object whose property I need to retrieve. A nice example is setupController() hook into which I may pass plain object from my unit tests to test setupController()‘s functionality.

// some route:
setupController(controller, model){
    this._super(...arguments);

    const name = Ember.get(model, 'name'); // ***

    controller.set('isNamePresentOnSetup', Ember.isPresent(name));
}

// in my unit tests I can use plain object:
...
const modelMock = { name: 'Bala' }; // plain object is enough because I use Ember.get instead of model.get() (see ***)?
const controllerMock = Ember.Object.create(); // has to be Ember.Object since I use controller.set() within setupController()

subject.setupController(controllerMock, modelMock);
assert.ok(controllerMock.get('isNamePresentOnSetup'), "property 'isNamePresentOnSetup' set up correctly if model name is present");
...

I could also user Ember.set(controller, 'isNamePresentOnSetup', Ember.isPresent(name)) and then pass plain controller mock into setupController(), too.

I think this is a good start since you are new in Ember and I am sure Ember gurus would have much more to add.
Relevant Ember docs:

https://guides.emberjs.com/v2.9.0/object-model/

https://guides.emberjs.com/v2.9.0/object-model/computed-properties/

https://guides.emberjs.com/v2.9.0/object-model/reopening-classes-and-instances/

UPDATE:
Using get() with chained paths works different than working with POJOs.
For example in objectInstance.get('a.b.c') if b is undefined the return value is undefined. Converting this to objectInstance.a.b.c when b is undefined would instead raise an exception.

Leave a Comment