0

I want to polyfill the Element.matches a method for IE.
I found these code on MDN:

if (!Element.prototype.matches) {
Element.prototype.matches = 
    Element.prototype.matchesSelector || 
    Element.prototype.mozMatchesSelector ||
    Element.prototype.msMatchesSelector || 
    Element.prototype.oMatchesSelector || 
    Element.prototype.webkitMatchesSelector ||
    function(s) {
        var matches = (this.document || 
    this.ownerDocument).querySelectorAll(s),
            i = matches.length;
        while (--i >= 0 && matches.item(i) !== this) {}
        return i > -1;            
    };
}

So I write some codes like:

function matches(node, selector) {
if (node.matches) {
    return node.matches(selector)
}

const match = node.matchesSelector || 
                            node.webkitMatchesSelector || 
                            node.mozMatchesSelector || 
                            node.msMatchesSelector || 
                            node.oMatchesSelector || 
                            function (s) {
           const matches = (node.ownerDocument || document).querySelectorAll(s) 
                                let i = matches.length
                                while (--i >= 0 && matches[i] !== node) {}
                                return i > -1
                           }
     return match(selector)
   }

Though, I know this will work on most browsers except IE I deleted most of the code, and tested it for IE, this worked:

function match(node, selector) {
        return node.msMatchesSelector(selector)
}

I wonder why this doesn't work:

function match(node, selector) {
      var isMatch = node.msMatchesSelector
      return isMatch(selector)
}
xiaojie Luo
  • 87
  • 10
  • Possible duplicate of [JavaScript function aliasing doesn't seem to work](https://stackoverflow.com/questions/1007340/javascript-function-aliasing-doesnt-seem-to-work) – Andreas Aug 07 '17 at 17:47
  • You use `querySelector()` in your polyfill instead of `querySelectorAll()` so the returned value will not have a `.length` and thus the loop can never be entered. – Patrick Roberts Aug 07 '17 at 17:51
  • Yeah you are right, I found and collected it but it still didn't work. – xiaojie Luo Aug 07 '17 at 17:54
  • Thanks Andreas.You pointed out the core problem. – xiaojie Luo Aug 07 '17 at 18:19

1 Answers1

2

The reason that

return node.msMatchesSelector(selector)

works and

var isMatch = node.msMatchesSelector
return isMatch(selector)

does not is because in the second case, the context of isMatch (the this) is undefined instead of node. You could write it like this, assuming IE supports bind():

var isMatch = node.msMatchesSelector.bind(node)
return isMatch(selector)

or simply just wrap the function to ensure you do not need support for bind():

var isMatch = function (s) { return node.msMatchesSelector(s) }
return isMatch(selector)

but that seems quite frivolous since you're only using the function once, so you might as well use the initial method in one line.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153