1

I happened to see this code in the Vue 2's document, this question is not about Vue, but Javascript syntax specifically. I hope there's someone out there can give me a clear explanation that I've been looking for. Here it goes, This piece of code on Vue's document:

var s = JSON.stringfy

someValue = s(arrayToStringfy)

If I understand it correctly, they are storing a reference of JSON.stringfy function to the variable s. So I'm trying to do the same thing with other function, it works as expected, but not until I try with document.getElementById. This piece of code below just doesn't work:

var doc = document.getElementById

doc('main') //Uncaught TypeError: Illegal invocation
    at <anonymous>

I did try to console the doc and it indeed said that doc is a function

console.log(typeof doc) // "function"

Is there something going on here that I didn't know about? Just want to make sure that you should not focus on the id 'main' as I'm a hundred percent sure there is a div with the id 'main'

KienHT
  • 1,098
  • 7
  • 11

3 Answers3

3

The problem here is that the this value inside the function depends on how it is called. For example:

function fn() {
  console.log(this.constructor.name);
}

fn(); // `this` will be the global object

const obj = {
  fn: fn
};
obj.fn(); // `this` will be `obj`

fn.call([]); // `this` will be an empty array

const boundFn = fn.bind(document);
boundFn(); // `this` will be the document

And document.getElementById() expects to be called with a Document object as its this value (A.K.A. as its context). Here's what the spec says (bold for emphasis):

The getElementById(elementId) method, when invoked, must return the first element, in tree order, within this’s descendants, whose ID is elementId, and null if there is no such element otherwise.

You can fix it by binding the value of this to document, like so:

var doc = document.getElementById.bind(document);
D. Pardal
  • 6,173
  • 1
  • 17
  • 37
1

The issue is context. When you take the reference to the function, you lose the function's context to document. So, in order to do what you are trying to, you need to bind the context:

var hello = document.getElementById.bind(document);

I took this answer from Can I assign document.getElementById to variable in javascript

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

There are also other ways like wrap it in a function.

var doc = function(elm) {
    return document.getElementById('#' + elm);
}

What I always do is taking all the elements that I need and export them as a JSON.

elements.js

export default {
  getOne: (elm) => document.querySelector(elm),
  getAll: (elm) => document.querySelectorAll(elm),
  body: document.querySelector('body'),
  form: document.querySelector('.search form'),
  search: document.querySelector('.search form input'),
  loading: document.querySelector('.loading'),
  error: document.querySelector('.error'),
  city: document.querySelector('.city'),
  date: document.querySelector('.date'),
  temp_main: document.querySelector('.main'),
  temp_min: document.querySelector('.temp-min'),
  temp_max: document.querySelector('.temp-max'),
  feels_like: document.querySelector('.feels-like'),
  pressure: document.querySelector('.pressure'),
  humidity: document.querySelector('.humidity'),
  wind: document.querySelector('.wind'),
  visibility: document.querySelector('.visibility'),
  description: document.querySelector('.description'),
  icon: document.querySelector('.icon'),
  map: document.querySelector('.map'),
};

app.js

import elms from './elements.js';

console.log(elms.getOne('span'))
console.log(elms.body)

so I always keep my code clean and I need a new element I just add it in elements.js

Refat Alsakka
  • 561
  • 2
  • 11
-2

To be completely honest with you, I don't know why that's happening. But what I can say is that the code should be like this:

 var doc = (x) => document.getElementById(x)

That's just a one-liner for doing:

var doc = function(x) {
  document.getElementById(x)
}

Depending on how you're looking at it

  • 2
    That is a simple syntax error and suffers from the same lack of understanding the problem that OP has. – connexo Mar 25 '21 at 09:44
  • Thank you for your answer, but unfortunately I'm not looking for a solution, I'm looking for an explanation, because sure enough I'm not gonna need to use this specific code in the future, I just want to know what's going on under the hood and what's the difference between those two functions. – KienHT Mar 25 '21 at 13:06