Mam następujący kod dla Ecma-Script-6 template literals
let person = {name: 'John Smith'};
let tpl = `My name is ${person.name}.`;
let MyVar="My name is "+ person.name+".";
console.log("template literal= "+tpl);
console.log("my variable = "+MyVar);
Wynik jest następujący:
template literal= My name is John Smith.
my variable = My name is John Smith.
to jest skrzypce. Próbowałem znaleźć dokładną różnicę, ale nie mogłem jej znaleźć, Moje pytanie brzmi, jaka jest różnica między tymi dwoma stwierdzeniami,
let tpl = `My name is ${person.name}.`;
I
let MyVar = "My name is "+ person.name+".";
Jestem już w stanie uzyskać ciąg MyVar
połączony z person.name
tutaj, więc jaki byłby scenariusz użycia literału szablonu?
javascript
node.js
ecmascript-6
template-strings
Naeem Shaikh
źródło
źródło
tpl === MyVar
? Jedyną różnicą jest składnia, za pomocą której zostały utworzone. Zwróć uwagę, że szablony, w przeciwieństwie do konkatenacji ciągów, zapewniają również funkcje znaczników, których można używać do takich rzeczy, jak automatyczne uciekanie.Odpowiedzi:
Jeśli używasz literałów szablonów tylko z symbolami zastępczymi (np.
`Hello ${person.name}`
), Tak jak w przykładzie pytania, wynik jest taki sam, jak po prostu łączenie ciągów. Subiektywnie wygląda lepiej i jest łatwiejszy do odczytania, zwłaszcza w przypadku ciągów wielowierszowych lub ciągów zawierających oba te znaki,'
a"
ponieważ nie musisz już uciekać przed tymi znakami.Czytelność to świetna funkcja, ale najbardziej interesującą rzeczą dotyczącą szablonów są otagowane literały szablonów :
let person = {name: 'John Smith'}; let tag = (strArr, name) => strArr[0] + name.toUpperCase() + strArr[1]; tag `My name is ${person.name}!` // Output: My name is JOHN SMITH!
W trzecim wierszu tego przykładu
tag
wywoływana jest funkcja o nazwie. Treść ciągu szablonu jest podzielona na wiele zmiennych, do których można uzyskać dostęp w argumentachtag
funkcji: sekcje literalne (w tym przykładzie wartośćstrArr[0]
isMy name is
i wartośćstrArr[1]
is!
) oraz substytucje (John Smith
). Literał szablonu zostanie oceniony na cokolwiektag
zwraca funkcja.ECMAScript wiki wymienia niektóre możliwe przypadki użycia, podobnie jak automatycznie ucieczki lub kodowania wejściowego lub lokalizację. Możesz utworzyć funkcję znacznika o nazwie,
msg
która wyszukuje części literalne, takie jakMy name is
i zastępuje je tłumaczeniami na język bieżącej lokalizacji, na przykład na język niemiecki:console.log(msg`My name is ${person.name}.`) // Output: Mein Name ist John Smith.
Wartość zwracana przez funkcję znacznika nie musi nawet być ciągiem znaków. Możesz utworzyć funkcję znacznika o nazwie,
$
która ocenia ciąg i używa go jako selektora zapytania w celu zwrócenia kolekcji węzłów DOM, jak w tym przykładzie :$`a.${className}[href=~'//${domain}/']`
źródło
msg
funkcji. Z pewnością możesz również przetłumaczyć wartości zastępcze.a.${className}[href=~'//${domain}/']
w konsoli (chrom i ustawić przedclassName=''
idomain=''
ale nie dostać węzłów DOM, ale tablicę ciągów: / (w drugim hadn w jsfiddle otrzymujemy błąd w konsoli: jsfiddle.net/d1fkta76 „Uncaught ReferenceError : $ nie jest zdefiniowane "- dlaczego?ES6
pojawia się nowy typ literału tekstowego, używając`
znaku wstecznego jako separatora. Te literały umożliwiają osadzanie podstawowych wyrażeń interpolacji ciągów, które są następnie automatycznie analizowane i oceniane.let actor = {name: 'RajiniKanth', age: 68}; let oldWayStr = "<p>My name is " + actor.name + ",</p>\n" + "<p>I am " + actor.age + " old</p>\n"; let newWayHtmlStr = `<p>My name is ${actor.name},</p> <p>I am ${actor.age} old</p>`; console.log(oldWayStr); console.log(newWayHtmlStr);
Jak widać, użyliśmy ... '' wokół serii znaków, które są interpretowane jako ciąg znaków, ale wszystkie wyrażenia formularza
${..}
są natychmiast analizowane i oceniane w tekście.Jedną naprawdę dobrą zaletą interpolowanych literałów ciągów jest to, że można je dzielić na wiele linii:
var Actor = {"name" : "RajiniKanth"}; var text = `Now is the time for all good men like ${Actor.name} to come to the aid of their country!`; console.log( text ); // Now is the time for all good men // to come to the aid of their // country!
Wyrażenia interpolowane
Każde prawidłowe wyrażenie może pojawić się wewnątrz
${..}
w interpolowanym ciągulit‐ eral
, w tym wywołania funkcji, wywołania wyrażeń funkcji wbudowanych, a nawet inneinterpo‐ lated string literals
!function upper(s) { return s.toUpperCase(); } var who = "reader" var text = `A very ${upper( "warm" )} welcome to all of you ${upper( `${who}s` )}!`; console.log( text ); // A very WARM welcome // to all of you READERS!
Tutaj, wewnętrzny interpolowany literał łańcuchowy $ {who} s 'był dla nas trochę przyjemniejszy, kiedy łączyliśmy zmienną who z
"s"
łańcuchem, w przeciwieństwie do who + "s". Ponadto, aby zachować notatkę, interpolowany literał ciągu jest dokładnielexically scoped
tam, gdzie się pojawia, a niedynamically scoped
w żaden sposóbfunction foo(str) { var name = "foo"; console.log( str ); } function bar() { var name = "bar"; foo( `Hello from ${name}!` ); } var name = "global"; bar(); // "Hello from bar!"
Korzystanie z
template literal
HTML jest zdecydowanie bardziej czytelne dzięki zmniejszeniu irytacji.Prosty stary sposób:
'<div class="' + className + '">' + '<p>' + content + '</p>' + '<a href="' + link + '">Let\'s go</a>' '</div>';
Z
ES6
:`<div class="${className}"> <p>${content}</p> <a href="${link}">Let's go</a> </div>`
Oznaczone literały szablonów
Możemy również oznaczyć
template
ciąg znaków, gdy znaktemplate
jest oznaczony,literals
podstawienia i są przekazywane do funkcji, która zwraca wynikową wartość.function myTaggedLiteral(strings) { console.log(strings); } myTaggedLiteral`test`; //["test"] function myTaggedLiteral(strings,value,value2) { console.log(strings,value, value2); } let someText = 'Neat'; myTaggedLiteral`test ${someText} ${2 + 3}`; // ["test ", " ", ""] // "Neat" // 5
W tym miejscu możemy użyć
spread
operatora do przekazania wielu wartości. Pierwszy argument - nazwaliśmy go ciągami znaków - jest tablicą wszystkich zwykłych łańcuchów (elementów między wszelkimi interpolowanymi wyrażeniami).następnie zbieramy wszystkie kolejne argumenty w tablicę zwaną wartościami przy użyciu znaku
... gather/rest operator
, chociaż oczywiście można było pozostawić je jako indywidualne nazwane parametry po parametrze string, tak jak zrobiliśmy to powyżej(value1, value2 etc)
.function myTaggedLiteral(strings,...values) { console.log(strings); console.log(values); } let someText = 'Neat'; myTaggedLiteral`test ${someText} ${2 + 3}`; // ["test ", " ", ""] // ["Neat", 5]
argument(s)
Zebrane w naszej tablicy wartości są wyniki już ocenianych interpolacji wyrażeń występujących w dosłownym strun. Atagged string literal
jest jak krok przetwarzania po oszacowaniu interpolacji, ale przed skompilowaniem końcowej wartości ciągu, co pozwala na większą kontrolę nad generowaniem ciągu z literału. Spójrzmy na przykład tworzenia plikure-usable templates
.const Actor = { name: "RajiniKanth", store: "Landmark" } const ActorTemplate = templater`<article> <h3>${'name'} is a Actor</h3> <p>You can find his movies at ${'store'}.</p> </article>`; function templater(strings, ...keys) { return function(data) { let temp = strings.slice(); keys.forEach((key, i) => { temp[i] = temp[i] + data[key]; }); return temp.join(''); } }; const myTemplate = ActorTemplate(Actor); console.log(myTemplate);
Surowe ciągi
nasze funkcje znaczników otrzymują pierwszy wywołany przez nas argument
strings
, którym jest plikarray
. Ale jest też dodatkowa porcja danych: surowe nieprzetworzone wersje wszystkich ciągów. Możesz uzyskać dostęp do tych nieprzetworzonych wartości ciągu za pomocą.raw
właściwości, na przykład:function showraw(strings, ...values) { console.log( strings ); console.log( strings.raw ); } showraw`Hello\nWorld`;
Jak widać,
raw
wersja łańcucha zachowuje sekwencję \ n ze zmianą znaczenia, podczas gdy przetworzona wersja łańcucha traktuje ją jak prawdziwą nową linię bez zmiany znaczenia.ES6
pochodzi z wbudowanej funkcji, które mogą być używane jako znak ciągiem znaków:String.raw(..)
. Po prostu przechodzi przez surowe wersjestrings
:console.log( `Hello\nWorld` ); /* "Hello World" */ console.log( String.raw`Hello\nWorld` ); // "Hello\nWorld"
źródło
Jest dużo czystszy i jak stwierdzono w komentarzach, jest typową cechą w innych językach. Inną rzeczą, która wydała mi się fajna, były podziały wierszy, bardzo przydatne podczas pisania łańcuchów.
let person = {name: 'John Smith', age: 24, greeting: 'Cool!' }; let usualHtmlStr = "<p>My name is " + person.name + ",</p>\n" + "<p>I am " + person.age + " old</p>\n" + "<strong>\"" + person.greeting +"\" is what I usually say</strong>"; let newHtmlStr = `<p>My name is ${person.name},</p> <p>I am ${person.age} old</p> <p>"${person.greeting}" is what I usually say</strong>`; console.log(usualHtmlStr); console.log(newHtmlStr);
źródło
Chociaż moja odpowiedź nie odnosi się bezpośrednio do pytania. Pomyślałem, że może być interesujące wskazanie jednej wady używania literałów szablonów na korzyść łączenia tablic.
Powiedzmy, że tak
let patient1 = {firstName: "John", lastName: "Smith"}; let patient2 = {firstName: "Dwayne", lastName: "Johnson", middleName: "'The Rock'"};
Dlatego niektórzy pacjenci mają drugie imię, a inni nie.
Gdybym chciał napisać pełne imię i nazwisko pacjenta
let patientName = `${patient1.firstName} ${patient1.middleName} ${patient1.lastName}`;
Wtedy to stałoby się „John undefined Smith”
Jednak gdybym to zrobił
let patientName = [patient1.firstName, patient1.middleName, patient1.lastName].join(" ");
Wtedy stałoby się to po prostu „John Smith”
EDYTOWAĆ
General_Twyckenham zwrócił uwagę, że łączenie na „” skutkowałoby dodatkową spacją między „John” i „Smith”.
Aby obejść ten problem, możesz ustawić filtr przed złączeniem, aby pozbyć się fałszywych wartości:
[patient1.firstName, patient1.middleName, patient1.lastName].filter(el => el).join(" ");
źródło
join
wersja da ci Johna Smitha z dodatkową spacją. Jak możesz sobie wyobrazić, często jest to niepożądane. Rozwiązaniem jest użycie w następującymap
sposób:[patient1.firstName, patient1.middleName, patient1.lastName].map(el => el).join(" ");
filter
taką funkcję miałem na myśli.