JavaScript 中的字符串插值?

发布于 2024-08-04 14:50:59 字数 138 浏览 3 评论 0原文

考虑这段代码:

var age = 3;

console.log("I'm " + age + " years old!");

除了字符串连接之外,还有其他方法可以将变量的值插入到字符串中吗?

Consider this code:

var age = 3;

console.log("I'm " + age + " years old!");

Are there any other ways to insert the value of a variable in to a string, apart from string concatenation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(18

望她远 2024-08-11 14:51:00

如果您想在 console.log 输出中进行插值,那么

console.log("Eruption 1: %s", eruption1);
                         ^^

这里的 %s 就是所谓的“格式说明符”。 console.log 内置了这种插值支持。

If you want to interpolate in console.log output, then just

console.log("Eruption 1: %s", eruption1);
                         ^^

Here, %s is what is called a "format specifier". console.log has this sort of interpolation support built-in.

半步萧音过轻尘 2024-08-11 14:51:00

您可以轻松地使用 ES6 模板字符串 并使用任何可用的转译器(如 babel)转译为 ES5。

const age = 3;

console.log(`I'm ${age} years old!`);

http://www.es6fiddle.net/im3c3euc/

You can do easily using ES6 template string and transpile to ES5 using any available transpilar like babel.

const age = 3;

console.log(`I'm ${age} years old!`);

http://www.es6fiddle.net/im3c3euc/

与风相奔跑 2024-08-11 14:51:00
let age = 3;

console.log(`I'm ${age} years old!`);

您可以使用反引号``ES6模板字符串

let age = 3;

console.log(`I'm ${age} years old!`);

You can use the backticks `` and ES6 template string

奶茶白久 2024-08-11 14:51:00

这是一个需要您提供带有值的对象的解决方案。如果您不提供对象作为参数,它将默认使用全局变量。但最好坚持使用参数,这样会干净得多。

String.prototype.interpolate = function(props) {
    return this.replace(/\{(\w+)\}/g, function(match, expr) {
        return (props || window)[expr];
    });
};

// Test:

// Using the parameter (advised approach)
document.getElementById("resultA").innerText = "Eruption 1: {eruption1}".interpolate({ eruption1: 112 });

// Using the global scope
var eruption2 = 116;
document.getElementById("resultB").innerText = "Eruption 2: {eruption2}".interpolate();
<div id="resultA"></div><div id="resultB"></div>

Here's a solution which requires you to provide an object with the values. If you don't provide an object as parameter, it will default to using global variables. But better stick to using the parameter, it's much cleaner.

String.prototype.interpolate = function(props) {
    return this.replace(/\{(\w+)\}/g, function(match, expr) {
        return (props || window)[expr];
    });
};

// Test:

// Using the parameter (advised approach)
document.getElementById("resultA").innerText = "Eruption 1: {eruption1}".interpolate({ eruption1: 112 });

// Using the global scope
var eruption2 = 116;
document.getElementById("resultB").innerText = "Eruption 2: {eruption2}".interpolate();
<div id="resultA"></div><div id="resultB"></div>

凝望流年 2024-08-11 14:51:00

尝试 kiwi,一个轻量级 JavaScript 模块用于字符串插值。

你可以做

Kiwi.compose("I'm % years old!", [age]);

或者

Kiwi.compose("I'm %{age} years old!", {"age" : age});

Try kiwi, a light-weight JavaScript module for string interpolation.

You can do

Kiwi.compose("I'm % years old!", [age]);

or

Kiwi.compose("I'm %{age} years old!", {"age" : age});
柒夜笙歌凉 2024-08-11 14:51:00

找不到我要找的东西,然后找到了它 -

如果您使用 Node.js,有一个内置的 util 包,其中包含一个格式函数,其工作原理如下:

util.format("Hello my name is %s", "Brent");
> Hello my name is Brent

巧合的是,这就是现在Node.js 中也内置了 console.log 风格 -

console.log("This really bad error happened: %s", "ReferenceError");
> This really bad error happened: ReferenceError

Couldn't find what I was looking for, then found it -

If you're using Node.js, there's a built-in utilpackage with a format function that works like this:

util.format("Hello my name is %s", "Brent");
> Hello my name is Brent

Coincidentally this is now built into console.log flavors too in Node.js -

console.log("This really bad error happened: %s", "ReferenceError");
> This really bad error happened: ReferenceError
幸福丶如此 2024-08-11 14:51:00

扩展Greg Kindel的第二个答案,您可以编写一个函数来消除一些样板文件:

var fmt = {
    join: function() {
        return Array.prototype.slice.call(arguments).join(' ');
    },
    log: function() {
        console.log(this.join(...arguments));
    }
}

用法:

var age = 7;
var years = 5;
var sentence = fmt.join('I am now', age, 'years old!');
fmt.log('In', years, 'years I will be', age + years, 'years old!');

Expanding on Greg Kindel's second answer, you can write a function to eliminate some of the boilerplate:

var fmt = {
    join: function() {
        return Array.prototype.slice.call(arguments).join(' ');
    },
    log: function() {
        console.log(this.join(...arguments));
    }
}

Usage:

var age = 7;
var years = 5;
var sentence = fmt.join('I am now', age, 'years old!');
fmt.log('In', years, 'years I will be', age + years, 'years old!');
江挽川 2024-08-11 14:51:00

从 ES6 开始,如果你想在对象键中进行字符串插值,如果你执行以下操作,你将得到一个 SyntaxError: Expected property name, got '${'

let age = 3
let obj = { `${age}`: 3 }

你应该执行以下操作:

let obj = { [`${age}`]: 3 }

Since ES6, if you want to do string interpolation in object keys, you will get a SyntaxError: expected property name, got '${' if you do something like:

let age = 3
let obj = { `${age}`: 3 }

You should do the following instead:

let obj = { [`${age}`]: 3 }
煞人兵器 2024-08-11 14:51:00

虽然模板可能最适合您描述的情况,但如果您拥有或想要可迭代/数组形式的数据和/或参数,则可以使用 String.raw

String.raw({
  raw: ["I'm ", " years old!"]
}, 3);

将数据作为数组,可以使用扩展运算符:

const args = [3, 'yesterday'];
String.raw({
  raw: ["I'm ", " years old as of ", ""]
}, ...args);

While templates are probably best for the case you describe, if you have or want your data and/or arguments in iterable/array form, you can use String.raw.

String.raw({
  raw: ["I'm ", " years old!"]
}, 3);

With the data as an array, one can use the spread operator:

const args = [3, 'yesterday'];
String.raw({
  raw: ["I'm ", " years old as of ", ""]
}, ...args);
左秋 2024-08-11 14:51:00

自定义灵活插值:

var sourceElm = document.querySelector('input')

// interpolation callback
const onInterpolate = s => `<mark>${s}</mark>`

// listen to "input" event
sourceElm.addEventListener('input', parseInput) 

// parse on window load
parseInput() 

// input element parser
function parseInput(){
  var html = interpolate(sourceElm.value, undefined, onInterpolate)
  sourceElm.nextElementSibling.innerHTML = html;
}

// the actual interpolation 
function interpolate(str, interpolator = ["{{", "}}"], cb){
  // split by "start" pattern
  return str.split(interpolator[0]).map((s1, i) => {
    // first item can be safely ignored
	  if( i == 0 ) return s1;
    // for each splited part, split again by "end" pattern 
    const s2 = s1.split(interpolator[1]);

    // is there's no "closing" match to this part, rebuild it
    if( s1 == s2[0]) return interpolator[0] + s2[0]
    // if this split's result as multiple items' array, it means the first item is between the patterns
    if( s2.length > 1 ){
        s2[0] = s2[0] 
          ? cb(s2[0]) // replace the array item with whatever
          : interpolator.join('') // nothing was between the interpolation pattern
    }

    return s2.join('') // merge splited array (part2)
  }).join('') // merge everything 
}
input{ 
  padding:5px; 
  width: 100%; 
  box-sizing: border-box;
  margin-bottom: 20px;
}

*{
  font: 14px Arial;
  padding:5px;
}
<input value="Everything between {{}} is {{processed}}" />
<div></div>

Custom flexible interpolation:

var sourceElm = document.querySelector('input')

// interpolation callback
const onInterpolate = s => `<mark>${s}</mark>`

// listen to "input" event
sourceElm.addEventListener('input', parseInput) 

// parse on window load
parseInput() 

// input element parser
function parseInput(){
  var html = interpolate(sourceElm.value, undefined, onInterpolate)
  sourceElm.nextElementSibling.innerHTML = html;
}

// the actual interpolation 
function interpolate(str, interpolator = ["{{", "}}"], cb){
  // split by "start" pattern
  return str.split(interpolator[0]).map((s1, i) => {
    // first item can be safely ignored
	  if( i == 0 ) return s1;
    // for each splited part, split again by "end" pattern 
    const s2 = s1.split(interpolator[1]);

    // is there's no "closing" match to this part, rebuild it
    if( s1 == s2[0]) return interpolator[0] + s2[0]
    // if this split's result as multiple items' array, it means the first item is between the patterns
    if( s2.length > 1 ){
        s2[0] = s2[0] 
          ? cb(s2[0]) // replace the array item with whatever
          : interpolator.join('') // nothing was between the interpolation pattern
    }

    return s2.join('') // merge splited array (part2)
  }).join('') // merge everything 
}
input{ 
  padding:5px; 
  width: 100%; 
  box-sizing: border-box;
  margin-bottom: 20px;
}

*{
  font: 14px Arial;
  padding:5px;
}
<input value="Everything between {{}} is {{processed}}" />
<div></div>

若有似无的小暗淡 2024-08-11 14:50:59

从 ES6 开始,您可以使用模板文字

const age = 3
console.log(`I'm ${age} years old!`)

PS 注意反引号的使用:``

Since ES6, you can use template literals:

const age = 3
console.log(`I'm ${age} years old!`)

P.S. Note the use of backticks: ``.

烈酒灼喉 2024-08-11 14:50:59

tl;dr

使用 ECMAScript 2015 的模板字符串文字(如果适用)。

说明

根据 ECMAScript 5 规范,没有直接的方法可以做到这一点,但 ECMAScript 6 有 模板字符串,在起草过程中也被称为准文字规格像这样使用它们:

> var n = 42;
undefined
> `foo${n}bar`
'foo42bar'

您可以在 {} 内使用任何有效的 JavaScript 表达式。例如:

> `foo${{name: 'Google'}.name}bar`
'fooGooglebar'
> `foo${1 + 3}bar`
'foo4bar'

另一个重要的事情是,您不必再担心多行字符串。您可以将它们简单地写为

> `foo
...     bar`
'foo\n    bar'

注意: 我使用 io.js v2.4.0 来评估上面显示的所有模板字符串。您还可以使用最新的 Chrome 来测试上面显示的示例。

注意: ES6 规范现已最终确定,但是尚未被所有主流浏览器实现。
根据 Mozilla 开发者网络页面,这将是从以下版本开始实现基本支持:Firefox 34、Chrome 41、Internet Explorer 12。如果您是 Opera、Safari 或 Internet Explorer 用户并且现在对此感到好奇,此测试床可用于试用,直到每个人都得到支持。

tl;dr

Use ECMAScript 2015's Template String Literals, if applicable.

Explanation

There is no direct way to do it, as per ECMAScript 5 specifications, but ECMAScript 6 has template strings, which were also known as quasi-literals during the drafting of the spec. Use them like this:

> var n = 42;
undefined
> `foo${n}bar`
'foo42bar'

You can use any valid JavaScript expression inside the {}. For example:

> `foo${{name: 'Google'}.name}bar`
'fooGooglebar'
> `foo${1 + 3}bar`
'foo4bar'

The other important thing is, you don't have to worry about multi-line strings anymore. You can write them simply as

> `foo
...     bar`
'foo\n    bar'

Note: I used io.js v2.4.0 to evaluate all the template strings shown above. You can also use the latest Chrome to test the above shown examples.

Note: ES6 Specifications are now finalized, but have yet to be implemented by all major browsers.
According to the Mozilla Developer Network pages, this will be implemented for basic support starting in the following versions: Firefox 34, Chrome 41, Internet Explorer 12. If you're an Opera, Safari, or Internet Explorer user and are curious about this now, this test bed can be used to play around until everyone gets support for this.

﹂绝世的画 2024-08-11 14:50:59

Douglas Crockford 的 Remedial JavaScript 包含一个 String.prototype.supplant 函数。它简短、熟悉且易于使用:

String.prototype.supplant = function (o) {
    return this.replace(/{([^{}]*)}/g,
        function (a, b) {
            var r = o[b];
            return typeof r === 'string' || typeof r === 'number' ? r : a;
        }
    );
};

// Usage:
alert("I'm {age} years old!".supplant({ age: 29 }));
alert("The {a} says {n}, {n}, {n}!".supplant({ a: 'cow', n: 'moo' }));

如果您不想更改 String 的原型,您可以随时将其调整为独立的,或将其放入其他名称空间或其他名称中。

Douglas Crockford's Remedial JavaScript includes a String.prototype.supplant function. It is short, familiar, and easy to use:

String.prototype.supplant = function (o) {
    return this.replace(/{([^{}]*)}/g,
        function (a, b) {
            var r = o[b];
            return typeof r === 'string' || typeof r === 'number' ? r : a;
        }
    );
};

// Usage:
alert("I'm {age} years old!".supplant({ age: 29 }));
alert("The {a} says {n}, {n}, {n}!".supplant({ a: 'cow', n: 'moo' }));

If you don't want to change String's prototype, you can always adapt it to be standalone, or place it into some other namespace, or whatever.

情绪 2024-08-11 14:50:59

警告:避免任何不允许您转义其自身分隔符的模板系统。例如,使用此处提到的 supplant() 方法将无法输出以下内容。

“由于我的 {age} 变量,我已经 3 岁了。”

简单的插值可能适用于小型独立脚本,但通常会带来这种设计缺陷,从而限制任何严肃的使用。老实说,我更喜欢 DOM 模板,例如:

<div> I am <span id="age"></span> years old!</div>

并使用 jQuery 操作: $('#age').text(3)

或者,如果您只是厌倦了字符串连接,总是有替代语法:

var age = 3;
var str = ["I'm only", age, "years old"].join(" ");

Word of caution: avoid any template system which does't allow you to escape its own delimiters. For example, There would be no way to output the following using the supplant() method mentioned here.

"I am 3 years old thanks to my {age} variable."

Simple interpolation may work for small self-contained scripts, but often comes with this design flaw that will limit any serious use. I honestly prefer DOM templates, such as:

<div> I am <span id="age"></span> years old!</div>

And use jQuery manipulation: $('#age').text(3)

Alternately, if you are simply just tired of string concatenation, there's always alternate syntax:

var age = 3;
var str = ["I'm only", age, "years old"].join(" ");
深海夜未眠 2024-08-11 14:50:59

当我还不知道如何正确执行并且只想快速记下一个想法时,我在很多语言中使用这种模式:

// JavaScript
let stringValue = 'Hello, my name is {name}. You {action} my {relation}.'
    .replace(/{name}/g    ,'Inigo Montoya')
    .replace(/{action}/g  ,'killed')
    .replace(/{relation}/g,'father')
    ;

虽然不是特别有效,但我发现它具有可读性。它始终有效,并且始终可用:

' VBScript
dim template = "Hello, my name is {name}. You {action} my {relation}."
dim stringvalue = template
stringValue = replace(stringvalue, "{name}"    ,"Luke Skywalker")     
stringValue = replace(stringvalue, "{relation}","Father")     
stringValue = replace(stringvalue, "{action}"  ,"are")

始终

* COBOL
INSPECT stringvalue REPLACING FIRST '{name}'     BY 'Grendel Mother'
INSPECT stringvalue REPLACING FIRST '{relation}' BY 'Son shoulder'
INSPECT stringvalue REPLACING FIRST '{action}'   BY 'made a gaping mortal-making wound upon.'

更新:

我原以为这是不言而喻的,但事实证明事实并非如此。只要有要循环的键/值对,您就可以应用此功能。

// JavaScript
let template = 'Hello, my name is {name}. You {action} my {relation}.'
let values = {
  name: 'Inigo Montoya',
  action: 'killed',
  relation, 'father',
};
let output = template;
for(let entry of Object.entries(values)){
  output = output.replace('{'+output[0]+'}',output[1]);
}
console.log(output);

我最近一直在 pl/SQL 中使用这个。

I use this pattern in a lot of languages when I don't know how to do it properly yet and just want to get an idea down quickly:

// JavaScript
let stringValue = 'Hello, my name is {name}. You {action} my {relation}.'
    .replace(/{name}/g    ,'Inigo Montoya')
    .replace(/{action}/g  ,'killed')
    .replace(/{relation}/g,'father')
    ;

While not particularily efficient, I find it readable. It always works, and its always available:

' VBScript
dim template = "Hello, my name is {name}. You {action} my {relation}."
dim stringvalue = template
stringValue = replace(stringvalue, "{name}"    ,"Luke Skywalker")     
stringValue = replace(stringvalue, "{relation}","Father")     
stringValue = replace(stringvalue, "{action}"  ,"are")

ALWAYS

* COBOL
INSPECT stringvalue REPLACING FIRST '{name}'     BY 'Grendel Mother'
INSPECT stringvalue REPLACING FIRST '{relation}' BY 'Son shoulder'
INSPECT stringvalue REPLACING FIRST '{action}'   BY 'made a gaping mortal-making wound upon.'

UPDATE:

I had thought it was self-evident, but it was made clear to me that it was not. You can apply this anytime you have a key/value pair to loop through.

// JavaScript
let template = 'Hello, my name is {name}. You {action} my {relation}.'
let values = {
  name: 'Inigo Montoya',
  action: 'killed',
  relation, 'father',
};
let output = template;
for(let entry of Object.entries(values)){
  output = output.replace('{'+output[0]+'}',output[1]);
}
console.log(output);

I've been using this in pl/SQL lately.

你是年少的欢喜 2024-08-11 14:50:59

如果你真的想用大锤来破解坚果,你可以使用 Prototype 的模板系统

var template = new Template("I'm #{age} years old!");
alert(template.evaluate({age: 21}));

You could use Prototype's template system if you really feel like using a sledgehammer to crack a nut:

var template = new Template("I'm #{age} years old!");
alert(template.evaluate({age: 21}));
反目相谮 2024-08-11 14:50:59

尝试 sprintf 库(一个完整的开源 JavaScript sprintf 实现)。例如:

vsprintf('The first 4 letters of the english alphabet are: %s, %s, %s and %s', ['a', 'b', 'c', 'd']);

vsprintf 接受一个参数数组并返回一个格式化字符串。

Try sprintf library (a complete open source JavaScript sprintf implementation). For example:

vsprintf('The first 4 letters of the english alphabet are: %s, %s, %s and %s', ['a', 'b', 'c', 'd']);

vsprintf takes an array of arguments and returns a formatted string.

几度春秋 2024-08-11 14:50:59

最简单的是

`my string ${VARIABLE}`

一种效率较低的方法来实现这一点,可以

function format(str, ...params) {
  for(const param of params)
    str = str.replace("%", param);
   return str;
}

format("My % string", "interpolation")

The simplest would be

`my string ${VARIABLE}`

a less efficient way to accomplish this would be

function format(str, ...params) {
  for(const param of params)
    str = str.replace("%", param);
   return str;
}

which can be used with

format("My % string", "interpolation")
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文