IEs understanding of 'this'

2020-07-25 23:52发布

问题:

In this code, Firefox sees 'this' as the element that was clicked and passes the href attribute through the right way.

IE seems to think that 'this' as [object window] instead. How would I get this to work the same way in both browsers?

Note: jQuery would be lovely, but is not an option for this project

var printElem = getElementsByClassName('print', 'a');
for(i in printElem){
    ObserveEvent(printElem[i], 'click', function(e){
        window.open(this.href, '', 'location=0,menubar=1,resizable=1,scrollbars=1,width='+810+',height='+700);
        cancelEvent(e);
    });
}

回答1:

I'm adding my two cents here as I think you can use it.

There was a contest 4 years ago to see who could write the best addEvent implementation. One of the main problems it tried to address was retaining this inside the event handler.

Here is one contest entry written by the creator of jQuery:

function addEvent( obj, type, fn ) {
  if ( obj.attachEvent ) {
    obj['e'+type+fn] = fn;
    obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
    obj.attachEvent( 'on'+type, obj[type+fn] );
  } else
    obj.addEventListener( type, fn, false );
}

(And of course to be symmetrical):

function removeEvent( obj, type, fn ) {
  if ( obj.detachEvent ) {
    obj.detachEvent( 'on'+type, obj[type+fn] );
    obj[type+fn] = null;
  } else
    obj.removeEventListener( type, fn, false );
}

Rename it to "ObserveEvent" if you wish.

There you have it, an 8 line implementation you can drop into your codebase - No libraries, no frameworks. And your this reference inside your handler works just fine.



回答2:

You can use the event target, like this:

    ObserveEvent(printElem[i], 'click', function(e){
            var target = e.target || e.srcElement;
            window.open(target.href, '', 'location=0,menubar=1,resizable=1,scrollbars=1,width='+810+',height='+700);
            cancelEvent(e);
    });


回答3:

The problem almost certainly stems from the ObserveEvent function using IE's attachEvent method, which (unlike addEventListener in other browsers) doesn't set this to the object being observed in the event handler.



回答4:

Another option: Create a closure to scope the element for the handler for each element:

var printElem = getElementsByClassName('print', 'a');
for(var i in printElem){
  (function(elem) { // elem === printElem[i] at time of execution later
    ObserveEvent(elem, 'click', function(e){
      window.open(elem.href, '', 'location=0,menubar=1,resizable=1,scrollbars=1,width='+810+',height='+700);
      cancelEvent(e);
    });
  })(printElem[i]); // immediately call the temp function with our element
}