Angular.js: Revert bdfc9c02 (restore [] as falsy)

Created on 27 Nov 2014  路  14Comments  路  Source: angular/angular.js

This was an awesome feature, and the problem is with Javascript: Empty anything should be falsy. Anyone who was surprised by [] being considered falsy is at fault for not reading the documentation, which clearly stated this behaviour.

Updating existing projects to compensate for the breaking change introduced by bdfc9c02 is no simple task, even just finding where it will break will be very labour-intensive, just for the dev to restore this functionality anyway.

misc core breaking change inconvenient

All 14 comments

I don't think it makes sense to revert bdfc9c02d021e08babfbc966a007c71b4946d69d as with it things like 'no' were considered falsy which was really surprising.

Now, speaking of [] - I would expect it to be truthy as it is in JS. More generally - I really do think that we should follow what JS do in this respect.

Strings like 'no' should not be falsy because 'no' is an actual word and possibly a valid value (also 'f' was a big gotcha, for which I answered a lot of questions on SO). But what is the use of an empty array or empty object? (empty object was never falsy in angular, but I'd like it to be) Data types should be persistent; ex I call GET example.com/collection/index?type=foo; ordinarily /collection returns an array, but there are no items in the collection of type foo, so it should return an empty array. The status of the call is success because nothing technically went wrong; but effectively I have nothing to work with from the response: Say I'm going to add some headings and run an ngRepeat

<table ng-show="collection">
  <thead>
    <th>Bar</th>
    <th>Qux</th>
  </thead>
  <tbody>
    <tr ng-repeat="item in collection">
      <td>{{ item.name }}</td>
      <td>{{ item.something }}</td>
    </tr>
</table>

In the above, there is absolutely no value when collection is empty, and it will be detrimental to show the headings with no rows (the table will look broken). With the new way, I have to do an extra step (ng-show="collection.length") to get the desired behaviour, when it's already the only use-case.

It would be nice if Javascript considered anything empty to be falsy, but we can't change Javascript as easily as Angular (also that would probably break the hell out of a lot of stuff if JS suddenly started to consider [] falsy).

@jshado1 I'm sure that others can come up with other arguments to not make [] falsy (ex.: https://github.com/angular/angular.js/issues/3969#issuecomment-34215426). We could argue for long but the real question is this: do we want to invent special rules or stick to the ones from JS?. Every time AngularJS expressions behave differently, as compared to JS, it requires explanation, documentation etc.

I don't see the bdfc9c02d021e08babfbc966a007c71b4946d69d frankly as it would force people to once again through the braking changes. For sure we can't do this in 1.3 and I would be against doing this in 1.4, but let's see what others got to say.

In the case of the referenced comment, I would expect the parser to compensate. ![] should be true (like how !null is natively true).

it might seem weird, but I feel like javascript semantics are basically the default language that most developers speak, so it's really unexpected if we do something "different", and treat non-(JS)-falsy values as falsy.

While it is arguably a weird thing in javascript, it's sort of the same in all of the languages javascript has inherited from, for instance:

  int* array = new int[0];
  if (array) {
    std::cout << "Array is NOT falsy" << std::endl;
  } else {
    std::cout << "Array is falsy" << std::endl;
  }
  array[0] = 1; // SIGSEGV

will allocate an array of integers (of length 0), and print the non-falsy string. While it's true that the collection is empty, testing if the collection is truthy or not is basically testing if the collection itself exists at all.

I don't think we want to re-break this, it's less confusing this way.

@caitp A falsy check does not check if something exists, it checks if it's equivalent to junk.

not junk, "falsy", like "null", "nil", "void 0", "undefined", "false", "0" --- these aren't gunk, but they're "zero-ish" (read: values which would be represented as, or coalesced to, a 0) values. (A reference to a valid object is not a zero-ish value)

A truthy/falsy check is for making a vague determination. If you want to know something specific, don't use a vague test.

It's a pretty specific determination, because falsy means something pretty specific =) What you're asking for is for us to interpret something non-falsy as falsy, and I don't think that we want to do that, for the simple reason that it confuses the heck out of people (as it did before the referenced sha was landed).

foo === false is specific. foo is exactly equal to false and nothing else.
foo == false is vague. foo is equal any of the following: null, '', false, 0 (or, hopefully, [])

@jshado1 once again, i think that we could argue here for long if [] and {} should be truthy or not but for me this is a wrong question. Imo we should decide if angularjs expressions should have different truthy / falsy semantic as compared to js. I simply see no reason of diverging here, i'm afraid...

My reasoning is that you had already diverged; you have the people who were originally confused using older version, plus now people who already understood the original functionality and are now confused by (arguably useful) functionality suddenly being broken.

Also, the people confused by the original functionality are currently working on that piece, so it's easier to isolate where the "problem" is; whereas something having to go back and change a bunch of stuff depending on that problem have to find all the instances.

Hi @jshado1 many developers found the original behavior extremely confusing as they expect that expressions follow javascript logic, and we realize that the original behavior was a mistake. I am sorry that this change is causing you some pain, but bdfc9c02d021e08babfbc966a007c71b4946d69d is not going to be reverted as we believe that the current behavior is the right behavior

If you were dead-set on this (breaking) change, v2 would have been a better time to introduce because that version will already introduce breaking changes :/

Was this page helpful?
0 / 5 - 0 ratings

Related issues

WesleyKapow picture WesleyKapow  路  3Comments

butchpeters picture butchpeters  路  3Comments

brijesh1ec picture brijesh1ec  路  3Comments

nosideeffects picture nosideeffects  路  3Comments

landed1 picture landed1  路  3Comments