Ist es möglich, eine Vorlagenzeichenfolge als normale Zeichenfolge zu erstellen?
let a="b:${b}";
und konvertieren Sie es dann in eine Vorlagenzeichenfolge
let b=10;
console.log(a.template());//b:10
ohne eval
, new Function
und andere Mittel der dynamischen Code - Generierung?
javascript
ecmascript-6
eval
template-strings
KOLANICH
quelle
quelle
Antworten:
Da Ihre Vorlagenzeichenfolge
b
dynamisch (zur Laufzeit) auf die Variable verweisen muss, lautet die Antwort: NEIN, ohne dynamische Codegenerierung ist dies nicht möglich.Aber damit ist
eval
es ziemlich einfach:quelle
a
Zeichenfolge und es wird viel weniger unsicher sein :let tpl = eval('`'+a.replace(/`/g,'\\`')+'`');
. Ich denke, wichtiger ist,eval
dass der Compiler Ihren Code nicht optimiert. Aber ich denke, dass es für diese Frage irrelevant ist.eval
. Denken Sie jedoch daran, dass ein Vorlagenliteral selbst eine Form von isteval
. Zwei Beispiele: var test =Result: ${alert('hello')}
; var test =Result: ${b=4}
; Beide führen am Ende beliebigen Code im Kontext des Skripts aus. Wenn Sie beliebige Zeichenfolgen zulassen möchten, können Sie dies auch zulasseneval
.In meinem Projekt habe ich so etwas mit ES6 erstellt:
UPDATE Ich habe die lodash-Abhängigkeit entfernt. ES6 verfügt über äquivalente Methoden zum Abrufen von Schlüsseln und Werten.
quelle
ReferenceError: _ is not defined
. Ist es Code nicht ES6 sondernlodash
spezifisch oder ...?Was Sie hier verlangen:
ist genau gleichwertig (in Bezug auf Leistung und Sicherheit)
eval
: der Fähigkeit, eine Zeichenfolge mit Code zu nehmen und diesen Code auszuführen; und auch die Fähigkeit des ausgeführten Codes, lokale Variablen in der Umgebung des Aufrufers zu sehen.In JS gibt es für eine Funktion keine Möglichkeit, lokale Variablen in ihrem Aufrufer anzuzeigen, es sei denn, diese Funktion ist dies
eval()
.Function()
Kann es sogar nicht.Wenn Sie hören, dass JavaScript so genannte "Vorlagenzeichenfolgen" enthält, können Sie davon ausgehen, dass es sich um eine integrierte Vorlagenbibliothek wie Moustache handelt. Ist es nicht. Es ist hauptsächlich nur String-Interpolation und mehrzeilige Strings für JS. Ich denke jedoch, dass dies für eine Weile ein weit verbreitetes Missverständnis sein wird. :((
quelle
template is not a function
.Nein, ohne dynamische Codegenerierung ist dies nicht möglich.
Ich habe jedoch eine Funktion erstellt, die eine reguläre Zeichenfolge in eine Funktion umwandelt, die mithilfe interner Vorlagenzeichenfolgen mit einer Wertekarte versehen werden kann.
Generate Template String Gist
Verwendung:
Hoffe das hilft jemandem. Wenn Sie ein Problem mit dem Code finden, aktualisieren Sie bitte das Gist.
quelle
var test = generateTemplateString('/api/${param1}/${param2}/')
console.log(test({param1: 'bar', param2: 'foo'}))
zurück/api/bar//
TLDR: https://jsfiddle.net/w3jx07vt/
Jeder scheint besorgt über den Zugriff auf Variablen zu sein. Warum nicht einfach übergeben? Ich bin sicher, es wird nicht zu schwierig sein, den variablen Kontext im Aufrufer abzurufen und weiterzugeben. Benutze das https://stackoverflow.com/a/6394168/6563504 , um die Requisiten von obj zu erhalten. Ich kann momentan nicht für dich testen, aber das sollte funktionieren.
Geprüft. Hier ist der vollständige Code.
quelle
${}
Zeichen nicht auszuwählen . Versuchen Sie:/(?!\${)([^{}]*)(?=})/g
Hier geht es darum, eine Funktion zu haben, die Zugriff auf die Variablen ihres Aufrufers hat. Aus diesem Grund wird Direct direkt
eval
für die Vorlagenverarbeitung verwendet. Eine mögliche Lösung wäre, eine Funktion zu generieren, die formale Parameter verwendet, die durch die Eigenschaften eines Wörterbuchs benannt sind, und sie mit den entsprechenden Werten in derselben Reihenfolge aufruft. Ein alternativer Weg wäre, etwas Einfaches wie dieses zu haben:Und für jeden, der den Babel-Compiler verwendet, müssen wir einen Abschluss erstellen, der sich an die Umgebung erinnert, in der er erstellt wurde:
quelle
eval
weil es nur mit einer globalenname
Variablenvar template = function() { var name = "John Smith"; var message = "Hello, my name is ${name}"; this.local = new Function('return
'+ message +';')();}
new Function
hat keinen Zugriff auf dievar name
in dertemplate
Funktion.Hier gibt es viele gute Lösungen, aber noch keine, die die ES6 String.raw-Methode verwenden . Hier ist mein Beitrag. Es hat eine wichtige Einschränkung dahingehend, dass nur Eigenschaften von einem übergebenen Objekt akzeptiert werden, was bedeutet, dass keine Codeausführung in der Vorlage funktioniert.
parts: ["Hello, ", "! Are you ", " years old?"]
args: ["name", "age"]
obj
anhand des Eigenschaftsnamens zu. Die Lösung wird durch eine flache Zuordnung auf einer Ebene begrenzt. Undefinierte Werte werden durch eine leere Zeichenfolge ersetzt, andere falsche Werte werden jedoch akzeptiert.parameters: ["John Doe", 18]
String.raw(...)
und zurückgeben.quelle
.replace()
wiederholt anzurufen ?.replace()
wünschen :) Ich denke, Lesbarkeit ist wichtig, also versuche ich, sie zu benennen, während ich selbst reguläre Ausdrücke verwende, um alles zuÄhnlich wie Daniels Antwort (und s.meijers Kern ), aber besser lesbar:
Hinweis: Dies verbessert das Original von s.meijer geringfügig, da es nicht mit Dingen wie übereinstimmt
${foo{bar}
(der reguläre Ausdruck erlaubt nur nicht geschweifte Klammern in${
und}
).UPDATE: Ich wurde nach einem Beispiel gefragt, also los geht's:
quelle
/\$\{(.*?)(?!\$\{)\}/g
(um mit geschweiften Klammern im Nest umzugehen). Ich habe eine funktionierende Lösung, bin mir aber nicht sicher, ob sie so portabel ist wie Ihre. Daher würde ich gerne sehen, wie dies auf einer Seite implementiert werden sollte. Meins benutzt aucheval()
.eval
viel offener für mögliche Fehler sind, die Sicherheitsprobleme verursachen würden, während meine Version lediglich eine Eigenschaft für ein Objekt von einem durch Punkte getrennten Pfad aus nachschlägt, was sicher sein sollte.Sie können beispielsweise den String-Prototyp verwenden
Aber die Antwort auf die ursprüngliche Frage ist auf keinen Fall.
quelle
Ich mochte die Antwort von s.meijer und schrieb meine eigene Version basierend auf seiner:
quelle
Ich benötigte diese Methode mit Unterstützung für Internet Explorer. Es stellte sich heraus, dass die Back Ticks nicht einmal von IE11 unterstützt werden. Ebenfalls; Verwenden
eval
oder es ist gleichwertigFunction
fühlt sich nicht richtig an.Für den, der es bemerkt; Ich benutze auch Backticks, aber diese werden von Compilern wie babel entfernt. Die von anderen vorgeschlagenen Methoden hängen von der Laufzeit ab. Wie gesagt; Dies ist ein Problem in IE11 und niedriger.
Das habe ich mir also ausgedacht:
Beispielausgabe:
quelle
eval('`' + taggedURL + '`')
einfach nicht.eval
. In Bezug auf Vorlagenliterale: Vielen Dank, dass Sie noch einmal darauf hingewiesen haben. Ich benutze Babel, um meinen Code zu transpilieren, aber meine Funktion wird anscheinend immer noch nicht funktionieren 😐Ich kann derzeit keine Kommentare zu vorhandenen Antworten abgeben, daher kann ich Bryan Raynors hervorragende Antwort nicht direkt kommentieren. Daher wird diese Antwort seine Antwort mit einer leichten Korrektur aktualisieren.
Kurz gesagt, seine Funktion kann die erstellte Funktion nicht tatsächlich zwischenspeichern, sodass sie immer neu erstellt wird, unabhängig davon, ob die Vorlage zuvor angezeigt wurde. Hier ist der korrigierte Code:
quelle
@Mateusz Moska, die Lösung funktioniert hervorragend, aber wenn ich sie in React Native (Build-Modus) verwendet habe, wird ein Fehler ausgegeben : Ungültiges Zeichen '`' , obwohl sie funktioniert, wenn ich sie im Debug-Modus ausführe.
Also habe ich meine eigene Lösung mit Regex aufgeschrieben.
Demo: https://es6console.com/j31pqx1p/
HINWEIS: Da ich die Grundursache eines Problems nicht kenne, habe ich ein Ticket im reaktionsnativen Repo https://github.com/facebook/react-native/issues/14107 ausgestellt , damit sie es können fix / führe mich ungefähr gleich :)
quelle
Immer noch dynamisch, scheint aber kontrollierter zu sein als nur eine nackte Bewertung zu verwenden:
https://repl.it/IdVt/3
quelle
Diese Lösung funktioniert ohne ES6:
Beachten Sie das
Function
Konstruktor wird immer im globalen Bereich erstellt, was möglicherweise dazu führen kann, dass globale Variablen von der Vorlage überschrieben werden, zrender("hello ${ someGlobalVar = 'some new value' }", {name:'mo'});
quelle
Da wir das Rad auf etwas neu erfinden, das eine schöne Funktion in Javascript wäre.
ich benutze
eval()
, was nicht sicher ist, aber Javascript ist nicht sicher. Ich gebe gerne zu, dass ich mit Javascript nicht besonders gut umgehen kann, aber ich hatte ein Bedürfnis, und ich brauchte eine Antwort, also habe ich eine gemacht.Ich habe mich dafür entschieden, meine Variablen
@
eher mit einem als mit einem zu stilisieren$
, insbesondere weil ich die mehrzeilige Funktion von Literalen verwenden möchte, ohne sie auszuwerten, bis sie fertig sind. Die variable Syntax ist also@{OptionalObject.OptionalObjectN.VARIABLE_NAME}
Ich bin kein Javascript-Experte, daher würde ich gerne Ratschläge zur Verbesserung erhalten, aber ...
Es folgt eine sehr einfache Implementierung
In meiner tatsächlichen Implementierung entscheide ich mich für die Verwendung
@{{variable}}
. Noch ein Satz Zahnspangen. Es ist absurd unwahrscheinlich, dass dies unerwartet auftritt. Die Regex dafür würde aussehen/\@\{\{(.*?)(?!\@\{\{)\}\}/g
Um das Lesen zu erleichtern
Wenn Sie nicht mit Regex erlebt, eine ziemlich sichere Regel ist jede nicht-alphanumerischen Zeichen zu entkommen, und nicht immer unnötig Buchstaben entkommen so viele entkam Buchstaben besondere Bedeutung zu praktisch alle Varianten von regex haben.
quelle
Sie sollten dieses winzige JS-Modul von Andrea Giammarchi von github ausprobieren: https://github.com/WebReflection/backtick-template
Demo (alle folgenden Tests geben true zurück):
quelle
Ich habe meine eigene Lösung gemacht, indem ich einen Typ mit einer Beschreibung als Funktion erstellt habe
und so:
quelle
Anstatt eval besser zu verwenden, wird Regex verwendet
Eval ist nicht zu empfehlen und wird dringend empfohlen. Verwenden Sie es daher nicht ( mdn eval ).
quelle