Why Ember.A() is used in component?


#1

Hello,

I often see code like this:

import Ember from 'ember';

...

const {
    ...     
    A,
    ...
} = Ember;

export default Component.extend({

    ...
    
    aProperty: A([]),
    
    ...
    
    anotherCP: computed(..., function() {
        ...
        
        return A([...]);
    }),
    
    ...
    
})

Why Ember.A is always used to wrap datas ? What are the advantages ?

Thanks,


#2

I’m new to Ember but it seems to make it easier to create an Ember.NativeArray. The syntax of A() is quicker and easier to read than Ember.A(). The code reads closer to the native JavaScript constructor Array then it would using Ember.A(). Also the shorthand decomposition using const {... A, ...} = Ember references methods/properties from the Ember object to a token in the current scope so the file doesn’t have tons and tons of Ember.(this|that|and|the|other|thing) everywhere.

One benefit besides readability could be that referencing the method/property into the current scope negates the need for JavaScript to “lookup” the property each time it is accessed with Ember.A. I don’t think lookup time is the reason people do it though because modern JS Engines handle those sorts of optimizations well anyways. I think it’s just for readability.

It might be interesting to note that Ember can extend the Array.prototypeso that you don’t ever even have to use Ember.A() at all. But it’s not a suggested way to work with Ember. Many JavaScript developers will tell you not to extend prototypes ever. Not in every case, but In this case I would agree.


#3

Thank you for your response.

no problem with ES6 syntax. In fact, I would like to know why some Ember developers use Ember.Array instead of native javascript Array.

Thanks,


#4

Ember.A has a number of methods that are not native Array proto methods (addObject, pushObjects, etc.). Ember hangs these methods off Array.proto by default but some engineers, like myself, opt out of these extension methods since it’s confusing to others on boarding not understanding how these methods are available but also they sometimes conflict with third-party libraries that hang their own prototype extension methods.

If a project disables the extension methods, your component/addon would not work in those environments. If you use Ember.A instead of relying on the extensions they’ll continue to work just fine.

Disabling Ember’s prototype extensions https://guides.emberjs.com/v2.4.0/configuring-ember/disabling-prototype-extensions/


#5

@jasonmit - I agree that not extending the prototype of JavaScript Objects is good practice. I do personally fall on the side of the fence where extending protos to implement coming standards as in polyfils is fine. Anyway though, I have been thinking backwards a bit (being new to Ember), I had assumed that Ember extended the prototypes of native Arrays when explicitly setting EXTEND_PROTOTYPES to true but I was mistaken. EXTEND_PROTOTYPES is set to true by default and the developer must explicitly set it to false to remove the prototype extensions. ( Thanks for the link )

Ember.Array as you stated adds non-native implementations as well as polyfils, like you wrote, this could be “confusing”. I’m writing my first large Ember Application right now and I sort of feel bad for not realizing this sooner. @Myrdhin I guess I read your question from a strange angle.

So, if Ember config is left to defaults, the EXTEND_PROTOTYPES configuration is set to be true and that means that the developer doesn’t have to explicitly use Ember.A to create an Ember.NativeArray because Array.prototype is extended already. However, regardless of the configuration it doesn’t hurt to use Ember.A and is actually encouraged when writing anything which could be used outside of the current Ember environment (such as add-ons, helpers or even components). @jasonmit So do I have that pretty much correct?

After having first read the following from the Ember.Array documentation:

When you are designing code that needs to accept any kind of Array-like object, you should use these methods instead of Array primitives because these will properly notify observers of changes to the array.

I was trying to juggle decisions such as “I’m only using an Array in my own code so I’ll just create an actual native JavaScript Array” and “This data will be shared between modules or accessed by my template so in this case I’ll use an Ember.Array”. In actuality now I see I overloaded the thought-train and that by default:

// By default if (EXTEND_PROTOTYPES === true) then:
const ingredients = ['laughter', 'sunshine', 'puppy dogs'];
// Would be the same as using
const ingredients = Ember.A( ['laughter', 'sunshine', 'puppy dogs'] );

@Myrdhin For my understanding now, the answer to the original question thanks to @jasonmit and the docs would be that either A. the developer has EXTEND_PROTOTYPES set to false so they must explicity call Ember.A when they need an Ember.NativeArray or B. The developer is writing an add-on or thinks their code might be dropped into a different project and is ensuring that it will run correctly in either configuration. I suppose that is the benefit of using Ember.A. Also, if EXTEND_PROTOTYPES is set to true there is still no big downside to using Ember.A because Ember.A utilizes Ember.Mixin.detect to first determine if the Array is already an Ember Mixin, so it won’t cause problems or do more work than needed (other than calling detect).


So, I am a week+ into an Ember project, I am going to keep EXTEND_PROTOTYPES set to default for now. I think since this is my first real Ember Application it would be good to learn within the suggested defaults before deciding that I already know what I want. I’m not a huge fan of convienance methods on the Array.prototype, but that could be a bias inherited from working in a volatile environment such as the web. Since Ember handles so many aspects of development, for the time being I am going to assume that in the confines of my Ember app, Ember knows best (in my case anyways).

Thank you both for the question and the responses and in advance for any advice you might leave. I want to learn the correct way and I hope that I now seem to have the right understanding?


#6

Thank you for all those informations


#7

@Myrdhin I found out 1 more thing. In the future Ember will allow developers to import modules which live on the Ember namespace using the ES6 import, so by destructuring at the top of your file it will make it trivial when that time comes to change over code to the new style without making any changes except for turning the destructuring statement into import statements.


#8

@mrosata Thank you. I will apply this principle to my future JS developments.