Я не уверен, что понимаю, что вы имеете в виду.
После некоторых комментариев ниже путаница в том, что означает "запускать его с функцией тега и без нее", означает:
let { id, html } = thread;
console.log("Without tag function", `${id("A-first-id")}${id("A-second-id")}${id("A-third-id")}`);
console.log("With tag function", html`${id("A-first-id")}${id("A-second-id")}${id("A-third-id")}`);
Результат:
Without tag function /test|0::0::A-first-id/test|0::0::A-second-id/test|0::0::A-third-id
With tag function node='/test|0::0::A-third-id'node=/test|0::0node=/test|0::0
Разница в том, что без функции тега она работает как задумано, и "A-first-id", "A-second -id "и" A-third-id "присутствует в результате. При использовании функции тега присутствует только «A-третий-идентификатор» (и формат также отличается).
Вопрос в том, почему «А-первый-идентификатор» и «А-второй-идентификатор» "теряются при использовании его с функцией-тегом.
Но я заметил, что вы перезаписываете фрагмент каждый раз, когда вызываете id
, а код в Symbol.toPrimitive
вызывается позднее , Вот почему вы получаете только последнюю строку "[ABC]-fourth-id"
и очищаете фрагмент с помощью if (isFragmentDefined) fragment = '';
"use strict";
class Thread {
constructor() {
this.html = (strings, ...interpolations) => {
var output = '';
var {
length
} = interpolations;
output += strings[0]
for (let i = 0; i < length; ++i) {
output += String(interpolations[i]) + strings[i + 1];
}
return output;
};
}
get id() {
var fragment;
return Object.defineProperties(function self(newFragment) {
console.log("fragment new '%s' old '%s'", newFragment, fragment);
fragment = newFragment; // overwrite fragment
return self;
}, {
[Symbol.toPrimitive]: {
value: hint => {
// this is called later, fragment is the last value
console.log("toPrimitive", fragment);
return fragment;
}
}
});
}
}
let thread = new Thread();
async function content() {
let {
id,
html
} = thread;
return html `
${id('A-first-id')}
${id('A-second-id')}
${id('A-third-id')}
${id('A-fourth-id')}
`;
}
content().then(x => console.log(x));
Запустите приведенный выше код, и вы получите:
fragment new 'A-first-id' old 'undefined'
fragment new 'A-second-id' old 'A-first-id'
fragment new 'A-third-id' old 'A-second-id'
fragment new 'A-fourth-id' old 'A-third-id'
toPrimitive A-fourth-id
toPrimitive A-fourth-id
toPrimitive A-fourth-id
toPrimitive A-fourth-id
A-fourth-id
A-fourth-id
A-fourth-id
A-fourth-id
Итак, сначала код в id
вызывается для КАЖДОГО вхождения в вашей строке, перезаписывая fragment
каждый раз. После этого вызывается toPrimitive
, и в нем установлен только последний фрагмент: "A-fourth-id"
.
Я почти уверен, что это не то, что вы хотели.
Я думаю что вы хотели:
fragment new 'A-first-id' old 'undefined'
fragment new 'A-second-id' old 'A-first-id'
fragment new 'A-third-id' old 'A-second-id'
fragment new 'A-fourth-id' old 'A-third-id'
toPrimitive A-first-id
toPrimitive A-second-id
toPrimitive A-third-id
toPrimitive A-fourth-id
A-first-id
A-second-id
A-third-id
A-fourth-id
И настоящая ошибка это ...
Когда я снова посмотрел на код и попытался объяснить, почему фрагмент был перезаписан Ударь меня: ты определяешь id
как добытчик. Поэтому, когда вы делаете:
let { id, html } = thread;
, вы фактически вызываете код в id
, и вы получаете функцию. Поэтому каждый раз, когда вы используете id
в вашей строке, он использует одну и ту же функцию с одним и тем же фрагментом.
Решение? Измените код, чтобы id
не был получателем.
Когда вы используете деконструкцию функций из объекта, функция больше не знает контекст. Это можно исправить, связав функцию в конструкторе:
class MyClass {
constructor() {
// Bind this to some functions
for (const name of ['one', 'two'])
this[name] = this[name].bind(this);
}
one(value) {
return this.two(value).toString(16);
}
two(value) {
return value * 2;
}
}
const my = new MyClass();
const {one, two} = my;
console.log(one(1000)); // Works since `one` was bound in the constructor
и для отладки:
- Браузер: в Google Chrome нажмите F12, выберите вкладку источника. Вы можете установить точки останова. Chrome пример
- Узел: см. пример узла
Обновление
Тег -функции для строк шаблона - это просто syntacti c sugar для передачи аргументов в функцию.
let { id, html } = thread;
// A tag function is just syntactic sugar:
html`${id("A-first-id")}${id("A-second-id")}${id("A-third-id")}`;
// for this:
html(["", "", "", ""], id("A-first-id"), id("A-second-id"), id("A-third-id"));
Без syntacti c sugar очевидно, что вы перезаписываете фрагмент каждый раз, когда вызываете id, и только последнее значение будет использоваться при преобразовании в примитивное значение.
Если вы не используете функцию тега, каждое значение преобразуется в значение примитива в каждом месте строки шаблона. Но когда вы используете его с функцией тега, вы получаете каждое значение в качестве параметра для вашей функции тега, и преобразование в примитивное значение не происходит, пока вы не преобразуете его в функцию тега. Поэтому вы получаете только последнее значение вашего фрагмента.