如何编写一个接受字符串和对象的函数并在字符串中插入该对象?

时间:2016-06-06 20:02:00

标签: javascript

大家好我需要编写一个函数,它接受一个字符串和对象并在字符串中插入该对象,所以这样的事情

// interpolate("Its {weather} outside", {weather: 'damn Hot'})
// returns 'It's damn hot outside'


// interpolate( "Hi my name is {name}", {name: 'John'});
// returns 'Hi my name is John'

无论对象有多深,所以也应如此

// interpolate("Hi my name is {contact.name}", {contact: {name: 'john'}});

我有点卡住了,起初我尝试将字符串拆分成一个数组,然后尝试将对象值放入数组中,然后将它连接在一起,但这并不适用于所有测试用例,有人可以帮我写这个功能并解释他们的解决方案吗?谢谢你

所以我尝试了类似这样的东西,但并不真正适用于所有测试用例,这是一个模板文字,但函数应该只是将这些值作为参数自己工作,否则我很困难。 。

function interpolate(strings, ...keys) {
  return (function(...values) {
    var dict = values[values.length - 1] || {};
    var result = [strings[0]];
    keys.forEach(function(key, i) {
      var value = Number.isInteger(key) ? values[key] : dict[key];
      result.push(value, strings[i + 1]);
    });
    return result.join('');
  });
}

var t1Closure = interpolate`${0}${1}${0}!`;
t1Closure('Y', 'A');  // "YAY!" 
var t2Closure = interpolate`${0} ${'foo'}!`;
console.log(t2Closure('Hello', {foo: 'World'}));  // "Hello World!"

好吧我越来越近所以我将问题分成两个函数并需要将它们组合起来,唯一的问题是我不知道如何在没有模板文字的情况下让最后一个用例工作

var something = "something";
var sub = function(str) {
   return str.replace(/#\{(.*?)\}/g,
    function(whole, expr) {
      return eval(expr)
    })
}

console.log(sub("hello #{something}"));



var objectValue = function(str, obj){

     for(key in obj) {
       if(obj.hasOwnProperty(key)) {
          var value = obj[key];
          return str + value;
      }
   }
}


console.log(objectValue("hi my name is ", {contact: {name: 'john'}}));

5 个答案:

答案 0 :(得分:3)

使用可怕的eval

如果你控制你传递的字符串并认为它是安全的,你可以使用eval



function interpolate (str, obj)  {
    return str.replace(/\{(.*?)\}/g, function (_, ref) {
        return eval('obj.' + ref);
    });
}

var output = interpolate("Its {weather} outside", {weather: 'damn Hot'});
console.log(output);

output = interpolate("Hi my name is {contact.name}", {contact: {name: 'john'}});
console.log(output);

output = interpolate("The highest bid is {rank[0].bid}", {rank: [{bid: 900}, {bid:600}]});
console.log(output);




请注意,如果给出类似'{x;alert("hi")}'的字符串,则上述函数将执行alert或任何代替的代码。因此,如果用户提供(或可以更改)字符串,则是一个很好的解决方案。

模板文字

它不遵循您的函数描述符,但template literals已经提供了您正在寻找的功能:



var weather = 'damn Hot';
var output = `It's ${weather} outside`;
console.log(output);

var contact = {name: 'john'};
var output = `Hi my name is ${contact.name}`;
console.log(output);




答案 1 :(得分:1)

你走了:

'use strict';
function interpolate(str, obj) {
  for (let prop in obj) {
    if (obj.hasOwnProperty(prop)) {
        str = str.replace(new RegExp(`{${prop}}`, 'g'), obj[prop]);
    }
  }
  return str;
}
console.log(interpolate("Its {weather} outside", {weather: 'damn Hot'}));
// Its damn Hot outside

答案 2 :(得分:0)

尝试renderjs

$("<p>Its {{:weather}} outside</p>").render({weather: 'damn Hot'}) 
-> <p>Its damn Hot outside</p>

答案 3 :(得分:0)

或lodash模板。 Lodash已经有很多方便的功能,你最终会在我看来使用很多。

var str = _.template('Its <%= weather %> outside')({weather: 'damn Hot'});

// If you wanted to use the {{:var}} syntax.
_.templateSettings.interpolate = /{{:([\s\S]+?)}}/g;
var str = _.template('Its {{:weather}} outside')({weather: 'damn Hot'});

答案 4 :(得分:0)

派对有点晚了,但万一你不能(不想)使用任何外部库或ES6,这就是这个想法:

function getMatches(s) {
    var regExp = /{([^}]*)}/g,
        matches = [],
        match;

    while ((match = regExp.exec(s)) != null) {
        matches.push(match[1]);
    }
    return matches;
}

function objValue(obj, i) {
    return obj[i];
}

function interpolate(s, obj) {
    var matches = getMatches(s),
        result = s;

    matches.forEach(function (match) {
        var props = match.split('.'),
            value = props.reduce(objValue, obj) || '';

        result = result.replace('{' + match + '}', value);
    });
    return result;
}

用法

interpolate("Its {weather} outside", { weather: 'damn Hot' });

JSFiddle