3

I'm using angular-1.2.1.js on ie8 and getting the error:

Object doesn't support property or method 'hasOwnProperty' (inside the angular ForEach method)

function forEach(obj, iterator, context) {
  var key;
  if (obj) {
    if (isFunction(obj)){
      for (key in obj) {
        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {
          iterator.call(context, obj[key], key);
        }
      }
    } else if ...

According to this stackoverflow post, hasOwnProperty does not work in ie8 (at least not on the window object)

I'm not sure if things are acting weird because I'm using ie8 mode on windows 8 ie, but hasOwnProperty works when I use

var a = {b:'c'}
a.hasOwnProperty('b')  //true

why is ie8 throwing an error and how can I fix? thanks

Community
  • 1
  • 1
stevethecollier
  • 1,034
  • 11
  • 13
  • 5
    Try testing on a real IE8, a lot of dumb things happen in compatibility mode that you can't trust. Can you provide the code where you're **actually** using `forEach`? – Ian Dec 10 '13 at 17:11
  • In IE8, `hasOwnProperty` doesn't work on DOM Elements (or other "host objects", I'd presume). – gen_Eric Dec 10 '13 at 17:20
  • 1
    Strange that Angular claims they've tested against IE8: http://docs.angularjs.org/guide/ie But is known not to work in IE11 with IE8 compatibility mode: https://github.com/angular/angular.js/issues/4137 the solution there was: `Object.prototype.hasOwnProperty.call(obj, key)` – HMR Dec 11 '13 at 00:57
  • I'm not using forEach anywhere – stevethecollier Dec 11 '13 at 14:57
  • Yeah, I was hoping there was a solution other than changing every instance of hasOwnProperty in the angular source to Object.prototype.hasOwnProperty.call(obj,key) – stevethecollier Dec 11 '13 at 16:56
  • 1
    @Jedininjaster I'm not sure if I'm right about this, but what if you checked the `window` object for the `hasOwnProperty` property? If it's not there, you define it. Something like `window.hasOwnProperty = window.hasOwnProperty || function (key) { return Object.prototype.hasOwnProperty.call(window, key); };`. This would be put on the page before any other scripts. Anything after it that tries to access the `window.hasOwnProperty` method will use either the native method (if it's defined) or the custom one that does the same thing just in a different way. Does that help? – Ian Dec 12 '13 at 01:32
  • @Ian, but that won't work for things like b.hasOwnProperty(c); will it? – Neil Feb 20 '14 at 11:51
  • 1
    @Neil It depends on what `b` is. If it's a normal JavaScript data type, it should work fine. If it's `window` or other host objects, such as an `Element`, it may not have that method. So in general, the solution is to use `Object.prototype.hasOwnProperty.call(b, c);` – Ian Feb 20 '14 at 15:59
  • 1
    related I guess http://stackoverflow.com/questions/8157700/object-has-no-hasownproperty-method-i-e-its-undefined-ie8 – Adriano Oct 14 '14 at 10:07
  • One [should not be using `obj.hasOwnProperty(…)`](https://stackoverflow.com/a/45014721/1048572) anyway – Bergi Sep 11 '22 at 17:11

2 Answers2

0

Use a map to convert the guarded statement:

 /* Check for existence */
 if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) 
    {
    iterator.call(context, obj[key], key);
    }

to a dispatch table:

 /* Map browser alias to stringified logic */
 var conditional = {"ie8": 
                    "key != 'prototype' && key != 'length' && key != 'name' && Object.prototype.hasOwnProperty.call(key, {})",

                    "w3c":
                    "key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)"
                   };

And a feature check to choose:

/* Ternary mapping of browser to logic */
var browser =  ("onpropertychange" in document) === true && (!!window.XDomainRequest) === true && (!!window.innerWidth) === false ? "ie8" : "w3c";

/* Evaluate valid result and pass to specified function */
if (eval(conditional[browser]) )
  {
  iterator.call(context, obj[key], key);
  }

References

Paul Sweatte
  • 24,148
  • 7
  • 127
  • 265
0

I also encountered this error & found this edit on angular.js Github Source to resolve this issue:

if (obj) {
     if (isFunction(obj)){
       for (key in obj) {
//-        if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) {
//+        // This uglyness around hasOwnProperty is for IE8 to work properly (hasOwnProperty doesn't exist)
/*+*/        if (key != 'prototype' && key != 'length' && key != 'name' && (obj.hasOwnProperty && obj.hasOwnProperty(key) || Object.prototype.hasOwnProperty.call(obj, key))) {
           iterator.call(context, obj[key], key);
         }
       }

enter image description here

There is one more edit to make console.log work on IE8 https://github.com/pjparra/angular.js/commit/bcbf9409f10f5988f6946a7b0381eee5e6518989

Source:https://github.com/pjparra/angular.js/commit/8c2ed24412620d68a760cfab70e4dc27a49b9e91

Pranav Singh
  • 17,079
  • 30
  • 77
  • 104