2

I am looking at the compat tables, and it seems like IE 11 supports all of ES5 except (under Miscellaneous) this feature: "Enumerable properties can be shadowed by non-enumerables". I don't understand what that means, despite the provided example.

Can I get away from using ES5 shim since IE11 supports most of it?

AngryHacker
  • 59,598
  • 102
  • 325
  • 594

2 Answers2

4

enter image description hereYes it is safe to drop ES5 shim in that scenario. I make websites available IE11 and common issues are custom variables, ES6 obviously and CSS calc() related bugs. Managed to make my own custom variable emulator using a map and used a similar approach CSS calc().

2

The length property they use here, actually comes from the prototype of the Function constructor, Function.prototype.length and returns the amount of arguments expected by the function. As you can see on the page I linked, the property is not enumerable, so for ... in should not enumerate the given property. The following snippet demonstrates that the property is not enumerable and therefore result will remain true.

var result = true;
for(var propertyName in Function) {
  if(propertyName == 'length') {
    result = false;
  }
}

var isLengthEnumerable = Function.prototype.propertyIsEnumerable('length');
console.log('Function.prototype.length is enumerable: ' + isLengthEnumerable);
console.log('Result: ' + result);

The snippet above gives us the following output:

Function.prototype.length is enumerable: false
Result: true

But in javascript, everything is an object and inherits properties from Object.prototype through its prototype chain, including Function. So what happens when we assign the same property length to Object.prototype?

var result1 = true;
var result2 = true;
Object.prototype.length = 42;
Object.prototype.otherProperty = 42;
for (var propertyName in Function) {
    if (propertyName == 'length') {
        result1 = false;
    }
    if (propertyName == 'otherProperty') {
        result2 = false;
    }
}

var isLengthEnumerable = Object.prototype.propertyIsEnumerable('length');
var isOtherPropertyEnumerable = Object.prototype.propertyIsEnumerable('otherProperty');
console.log('Object.prototype.length is enumerable: ' + isLengthEnumerable);
console.log('Object.prototype.otherProperty is enumerable: ' + isOtherPropertyEnumerable);
console.log('Result1: ' + result1);
console.log('Result2: ' + result2);

The above snippet gives us the following results:

Object.prototype.length is enumerable: true
Object.prototype.otherProperty is enumerable: true
Result1: true
Result2: false

As the Object.prototype.length property we just assigned is enumerable, you would expect that result1 would now be false. But because Function already has a length property (although not enumerable), the length property inherited from Object.prototype is not enumerated. The property has been shadowed.

This is what doesn't happen in IE11, there Object.prototype.length will be enumerated anyways and result1 will become false as well.

Alexander Derck
  • 13,818
  • 5
  • 54
  • 76