Should I avoid adding arbitrary fields to HTML elements?

Solution 1:

It should work, but it's not a good idea, because a future change to the DOM specification might add those properties, and your code would conflict.

The DOM API already provides a place for application-defined string data, the dataset property, which corresponds to data-XXX attributes. So you can write:

element.dataset.message = 'Hello, world';

There's nothing equivalent for functions, though. Instead of making it a property, you could just use a regular function.

function greet(element) {
    alert(element.dataset.message);
}

Solution 2:

DOM elements are not "namespaces" for related stuff, they are entities with a specific purpose, which is reflected as a particular set of data and behavior. Although there are some objects in JavaScript that serve the purpose of namespacing related functionality (Math, Intl, etc.), they usually are unique and "famous" enough to be a good exception to the rule.

If you want to associate a particular behavior and/or data with some DOM element, create a separate entity; it can be a full-blown class:

class ElementGreeter {
  constructor(element, friendElement) {
    this.element = element;
    this.friendElement = friendElement;
  }

  greetPrimary() {
    this.greet(this.element.innerText);
  }

  greetFriend() {
    this.greet(this.friendElement.innerText);
  }

  greet(message) {
    alert(message);
  }
}

… or a simple function:

const createGreeter = (propName) => (element) => alert(element[propName]);

const greet = createGreeter("innerText");

greet(element);
greet(friendElement);