Since these are processed values that are converted to actual strings in the DOM, the designers probably decided to implement a consistent pattern to identify strings and make sure they are safe before being output to the DOM.
Here are some relevant code snippets from the source to see what is happening when the bindAttr class binding is processed.
// Handle classes differently, as we can bind multiple classes
var classBindings = attrs['class'];
if (classBindings != null) {
var classResults = EmberHandlebars.bindClasses(this, classBindings, view, dataId, options);
ret.push('class="' + Handlebars.Utils.escapeExpression(classResults.join(' ')) + '"');
delete attrs['class'];
}
Note the call to
Handlebars.Utils.escapeExpression
If we look at handlebars source
we find
escapeExpression: function(string) {
// don't escape SafeStrings, since they're already safe
if (string instanceof Handlebars.SafeString) {
return string.toString();
} else if (string == null || string === false) {
return "";
}
// Force a string conversion as this will be done by the append regardless and
// the regex test will do this transparently behind the scenes, causing issues if
// an object's to string has escaped characters in it.
string = string.toString();
if(!possible.test(string)) { return string; }
return string.replace(badChars, escapeChar);
},
By force escaping the strings Ember and handlebars increase the security and prevent some exploit vectors.
Rails does something similar.
Because the string has a colon next to it, I think that indicates that it is treated as a special kind of entity and it is parsed and passed back to the DOM in a known safe way.
To me it is just sugar around the syntax booleanProperty:class-if-true. When you always want the class, you just omit the boolean property, and it becomes :class-always-here.