Why can't I directly assign document.getElementById to a different function?

后端 未结 5 1942
悲&欢浪女
悲&欢浪女 2020-11-30 12:20

So I\'m trying to define a function g() that is like document.getElementById. The following works just fine:

var g = function(id){return document.getElementB         


        
相关标签:
5条回答
  • 2020-11-30 13:04

    As lonesomeday's answer already shows, the problem is with the execution context. I would like to add that there is a way to create a function with the execution context. Open your browser's Developer Tools for this page and try the following in the Console:

    > document.getElementById('notify-container');
    // <div id="notify-container"></div>
    
    > var _d = document.getElementById;
    // undefined
    
    > _d
    // ƒ getElementById() { [native code] }
    
    > _d('notify-container');
    // Uncaught TypeError: Illegal invocation
    //     at <anonymous>:1:1
    

    As before, directly invoking the variable _d which is assigned to document.getElementById fails. But you can use Function.prototype.bind to bind the execution context.

    The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

    > var d = document.getElementById.bind(document);
    // undefined
    
    > d('notify-container');
    // <div id="notify-container"></div>
    

    You also do not have to worry much about browser compatibility if you want to use bind: See https://caniuse.com/#feat=es5.

    0 讨论(0)
  • 2020-11-30 13:08

    The problem is the context. document.getElementById(xxx) runs in the context of document, but when you assign it to something, you get a TypeError because the context is probably window. See this jsFiddle: http://jsfiddle.net/minitech/as3AQ/

    So, you could use call or apply, but that's ugly. Just do the second way instead, or assign it to document and assign document to something if your objective is to minify your code.

    0 讨论(0)
  • 2020-11-30 13:09

    The problem is that of context. When you fire an object's function, it is fired with the object as the value of this (unless you specify otherwise). g = document.getElementById puts the function getElementById into the variable g, but doesn't set the context.

    Therefore, when you run g(someId), there is no context on which the function can run. It is run with the global object window as the value of this, and that doesn't work. (To be precise, it doesn't work because you could be operating with any document object, not just window.document, and you haven't specified one.)

    You could get around this with call, where you set the context:

    g.call(document, someId);
    

    However, this isn't an improvement over the original!

    0 讨论(0)
  • 2020-11-30 13:10

    Because when you call "g('somestr')" the "this" value is bound to the "window" and "document.getElementById" seens to expect to be bound to "document" instead "window"(makes sense to me =) ). Doing:

    var g = document.getElementById;
    g('somestr');
    

    is like:

    document.getElementById.call(window, 'somestr');
    
    0 讨论(0)
  • 2020-11-30 13:16

    @minitech and @Tim Down Thanks a lot for your feedback.

    We have a lot of old code which worked like this

    var $ = document.getElementById;
    $("First");
    

    It Failed with error message in modern browsers Uncaught TypeError: Illegal invocation

    All i did is replaced it as

    var $ = function(x) { return document.getElementById(x); };
    $("First");
    

    Now we are back in the game :)

    0 讨论(0)
提交回复
热议问题