Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Ah, thanks! Got it. Okay that's wild. I would not expect that to be stable across dynamically-generated template functions, but it seems to work!


This is how lit-html implements efficient re-renders of the same template at the same location in DOM. It uses the template strings identity to mark that some DOM was generated from a specific template, and if rendering there again it just skips all the static parts of the template and updates the bound values.

Tagged template literals are crazy powerful, and it would be really neat to add some of that magic to other language features. If functions could access the callsite, you could implement React hooks without the whole hooks environment. Each hook could just cache it's state off the callsite object.


The key thing to note here is that it is completely _lexical_ in scope - this only generates one tagged template even when called multiple times:

  function lexicalMagic() {
    const callHistory = [];
  
    function tag(strings, ...values) {
      callHistory.push(strings);
      // Return a freshly made object
      return {};
    }

    function evaluateLiteral() {
      return tag`Hello, ${"world"}!`;
    }
    return { evaluateLiteral, callHistory }
  }
We can create multiple "instances" of our closures, just as we expect and they do in fact produce distinct everything-else:

  > const first = lexicalMagic()
  > const second = lexicalMagic()
  > first.evaluateLiteral === second.evaluateLiteral
  false
  > first.callHistory === second.callHistory
  false
Using them doesn't behave any differently than the unclosured versions (as expected):

  > first.evaluateLiteral() === first.evaluateLiteral()
  false
  > first.callHistory[0] === first.callHistory[1]
  true
  > second.evaluateLiteral() === second.evaluateLiteral()
  false
  > second.callHistory[0] === second.callHistory[1]
  true
However, there is only one instance of the template literal, not two as we might expect. This is really helpful for some cases, but it definitely is surprising given the rest-of-JS:

  > first.callHistory[0] === second.callHistory[1]
  true




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: