繁体   English   中英

如何在 JavaScript 中进行字符串插值?

[英]How can I do string interpolation in JavaScript?

考虑这段代码:

var age = 3;

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

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

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

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

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

tl;博士

如果适用,请使用 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 Developer Network pages ,这将在以下版本中实现基本支持:Firefox 34、Chrome 41、Internet Explorer 12。如果您是 Opera、Safari 或 Internet Explorer 用户并且现在对此感到好奇, 这个测试台可以用来玩玩,直到大家都支持为止。

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 的原型,您可以随时将其调整为独立的,或者将其放置到其他名称空间中,或其他任何东西。

注意事项:避免使用任何不允许您转义其自己的分隔符的模板系统。 例如,使用此处提到的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(" ");

当我还不知道如何正确地做到这一点并且只想快速获得一个想法时,我会在很多语言中使用这种模式:

// 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.'

如果你真的想用大锤敲碎坚果,你可以使用Prototype 的模板系统

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

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

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

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

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

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

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

您可以轻松地使用 ES6 template string并使用任何可用的转译器(如 babel)转译为 ES5。

const age = 3;

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

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

最简单的应该是

`my string ${VARIABLE}`

实现这一目标的效率较低的方法是

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

可以与

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

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

你可以做

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

或者

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

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

 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>

使用`重音,也称为反引号 )代替单引号( ' )或双引号( " )和美元符号/方括号${ variable }

例如:

 console.log( `current date: ${new Date()}` ); 

在此处阅读有关模板文字的更多信息。

let age = 3;

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

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

扩展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!');

我可以用一个例子告诉你:

 function fullName(first, last) { let fullName = first + " " + last; return fullName; } function fullNameStringInterpolation(first, last) { let fullName = `${first} ${last}`; return fullName; } console.log('Old School: ' + fullName('Carlos', 'Gutierrez')); console.log('New School: ' + fullNameStringInterpolation('Carlos', 'Gutierrez'));

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

如果您使用的是 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

从 ES6 开始,如果你想在对象键中进行字符串插值,你会得到一个SyntaxError: expected property name, got '${' if you do like:

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

您应该改为执行以下操作:

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

为@Chris Nielsen 的帖子的ES6版本替换更多内容。

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

string = "How now ${color} cow? {${greeting}}, ${greeting}, moo says the ${color} cow.";

string.supplant({color: "brown", greeting: "moo"});
=> "How now brown cow? {moo}, moo, moo says the brown cow."

在旧版浏览器中使用模板语法会失败,这对于创建供公众使用的 HTML 很重要。 使用连接是乏味且难以阅读的,特别是如果您有很多或很长的表达式,或者如果您必须使用括号来处理数字和字符串项目的混合(两者都使用 + 运算符)。

PHP 使用非常紧凑的符号扩展包含变量甚至某些表达式的引用字符串: $a="the color is $color";

在 JavaScript 中,可以编写一个高效的函数来支持这一点: var a=S('the color is ',color); ,使用可变数量的参数。 虽然在这个例子中没有比串联的优势,但当表达式变长时,这种语法可能会更清晰。 或者可以使用美元符号来表示使用 JavaScript 函数的表达式的开始,就像在 PHP 中一样。

另一方面,编写一个有效的解决方法来为旧版浏览器提供类似模板的字符串扩展并不难。 可能已经有人这样做了。

最后,我认为 sprintf(如在 C、C++ 和 PHP 中)可以用 JavaScript 编写,尽管它的效率会比其他这些解决方案低一些。

自定义灵活插值:

 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>

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM