Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do I understand this Function.prototype.call() code correctly?

Tags:

javascript

The code:

var content = Array.prototype.map.call(document.getElementsByTagName("p"), function(e) {
  return e.innerHTML;
}); 

It's from p. 367 of JavaScript: The Definitive Guide, 6th ed.

Here's what I think is happening in this code.

The variable content is being assigned the result of a .map() call on the NodeList of paragraph tags returned by document.getElementsByTagName("p").

The .map() method is accessed from the Array.prototype, and its this value is set to be the paragraph tag NodeList using .call(). Since .map() applies a function that has access to item, index, array, the e in function(e) is the item of the NodeList.

So the content variable ends up being comprised of the result of .innerHTML calls on each of the Element type Nodes in the NodeList made up of paragraph tags in the current document.

.innerHTML will return the text of a given HTML element if it has no other nodes inside it. Otherwise it will return the HTML nodes inside it.

Is that correct? I've tried:

  1. Reading the MDN documentation on Function.prototype.call
  2. Searching Programmers SE I found Misunderstanding Scope, which I'm not certain how to interpret. It claims the MDN documentation is incomplete.
  3. Reading more in the Definitive book.
  4. Messing around in JSFiddle - the code acts as expected, I just want to know how it's doing what it does.
like image 613
phoenixdown Avatar asked Jul 31 '14 04:07

phoenixdown


People also ask

What is function prototype call?

A function prototype is a definition that is used to perform type checking on function calls when the EGL system code does not have access to the function itself. A function prototype begins with the keyword function, then lists the function name, its parameters (if any), and return value (if any).

What's the difference between function prototype apply and function prototype call?

apply and Function. prototype. call are methods that allow you to call a function with a specific this value and arguments. The main difference between the two is that apply lets you pass in an array of arguments, while call requires you to list the arguments one by one.

What is the difference between using call () and apply () to invoke a function with multiple arguments?

The Difference Between call() and apply() The difference is: The call() method takes arguments separately. The apply() method takes arguments as an array. The apply() method is very handy if you want to use an array instead of an argument list.

What is this in a function?

The this keyword refers to the object the function belongs to, or the window object if the function belongs to no object. It's used in OOP code, to refer to the class/object the function belongs to For example: function foo() { this.


1 Answers

Yup, that's exactly that's happening.

Just to be really picky:

.innerHTML will return the text of a given HTML element if it has no other nodes inside it. Otherwise it will return the HTML nodes inside it.

.innerHTML always returns the HTML contents of an element, regardless of whether it contains children or not. It's just hard to spot the difference between the text of an element and HTML of an element when it contains no children (but there is a difference!).

HTML:

<div>&lt;</div>

JS:

console.log(document.getElementsByTagName("div")[0].innerHTML); // "&lt;"
console.log(document.getElementsByTagName("div")[0].textContent); // "<"

FWIW, this is possible in the first place because a lot of JavaScript methods prefer duck typing to relying on inheritance

When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck

Because of this, map() will happily let you map() any object which feels like an array (i.e. has a .length property).

You could also have used:

var content = [].map.call(document.getElementsByTagName("p"), function(e) { return e.innerHTML; }); 

... but the former is preferred because you don't have to create, then throwaway, the array to get access to the map() function.

like image 109
Matt Avatar answered Nov 15 '22 14:11

Matt