【问题标题】:Replace all using indexOf and while loop in String.prototype在 String.prototype 中使用 indexOf 和 while 循环替换所有内容
【发布时间】:2016-07-27 10:40:25
【问题描述】:

我正在尝试在我的代码中实现这个字符串替换功能:

String.prototype.replaceAll = function(f,r) {
  if (f != r) {
    while (this.indexOf(f) !== -1) {
      this = this.replace(f,r);
    }
  } else {
    return this;
  }
};

我已经尝试过使用它:

String.prototype.replaceAll = function(f,r) {
  return this.split(f).join(r);
};

但是最后一个替换函数在搜索表达式中有两个或多个字符时不起作用

所以我真的需要在 while 循环中使用第一个函数。

有人知道第一个函数显示的问题是什么吗?

【问题讨论】:

  • 好吧,你在实现中使用String.prototype.replace有点作弊。但是你知道如果你想全部替换你可以使用string.replace(/find/g, 'replacement'),对吧?
  • 感谢您的回答!我知道我可以使用 /g 和 /gi。事实上,我的代码已经在使用 replace /g 了。但是在某些时候,我想写一个小函数来使用 RegExp 来证明是必要的。但正如我们所见,while 循环没有任何理由不起作用。
  • 我在下面提供了更深入的答案

标签: javascript string replace prototype indexof


【解决方案1】:

字符串在 JavaScript 中是不可变的,所以这样的事情不会起作用

// can't reassign `this` in String.prototype method !
this = this.replace(f,r)

相反,您必须从函数中返回一个新字符串

String.prototype.replaceAll = function replaceAll(f,r) {
  if (this.indexOf(f) === -1)
    return this.toString()
  else
    return this.replace(f, r).replaceAll(f,r)
}

console.log('foobar foobar'.replaceAll('foo', 'hello')) // => 'hellobar hellobar'
console.log('foobar foobar'.replaceAll('o', 'x'))       // => 'fxxbar fxxbar'

如果您不介意依赖像 String.prototype.indexOfString.prototype.replace 这样的内置插件,那么这就是简短的答案


如果您也想从头开始实现这些,您可以使用非常基本的 JavaScript 来实现。您不必使用 while 循环`。你可以,但是像……这样的陈述

所以我真的需要在while循环中使用第一个函数。

……是假的。


让我们从一个基本的find 函数开始。这就像String.prototype.indexOf

function find(s, x) {
  function loop(s, pos) {
    if (s.substring(0, x.length) === x)
      return pos
    else if (s === '')
      return -1
    else
      return loop(s.substring(1), pos + 1)
  }
  return loop(s, 0)
}

console.log(find('foobar', 'f'))   // => 0
console.log(find('foobar', 'bar')) // => 3
console.log(find('foobar', 'x'))   // => -1
console.log(find('foobar', ''))    // => 0

然后是一个replace 函数,该函数用于将x 的单个实例替换为字符串y 中的s

function replace(s, x, y, idx) {
  // idx is an optional parameter here for optimizing replaceAll
  // you'll see it used in the next example
  if (idx === undefined)
    return replace(s, x, y, find(s, x))
  else if (idx === -1)
    return s
  else
    return s.substring(0, idx) + y + s.substring(idx + x.length)
}

console.log(replace('foobar', 'foo', 'hello')) // => 'hellobar'
console.log(replace('foobar', 'bar', 'hello')) // => 'foohello'

那么,实现replaceAll就是一个简单的递归函数

function replaceAll(s, x, y) {
  var idx = find(s, x)
  if (idx === -1)
    return s
  else
    // use 4th parameter in replace function so index isn't recalculated
    return replaceAll(replace(s, x, y, idx), x, y)
}

console.log(replaceAll('foobar foobar', 'foo', 'hello')) // => 'hellobar hellobar'
console.log(replaceAll('foobar foobar', 'o', 'x')   )    // => 'fxxbar fxxbar'

如果你愿意,你可以在String.prototype 上实现所有这些功能,所以像'foobar'.replaceAll('o', 'x') 这样的东西可以工作。

如果你不喜欢find,可以使用原生的String.prototype.indexOf。另一方面,如果您将此作为练习,并且尝试从头开始实施,您甚至可以不依赖我在这里使用的String.prototype.substring


另外,你的代码在这里运行良好

String.prototype.replaceAll = function(f,r) {
  return this.split(f).join(r);
};

'foobar foobar'.replaceAll('foo', 'hello')
// => "hellobar hellobar"

'foobar foobar'.split('foo').join('hello')
// => "hellobar hellobar"

【讨论】:

  • 谢谢娜奥米克!我没有注意到String 是一个原始值,所以它是不可变的(不像ArrayObject)。
【解决方案2】:
function(f,r)
{
var str=this;
if (f != r) {
    while (str.indexOf(f) !== -1) {
       str=str.replace(f,r);
    }
}
return str.toString();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-21
    • 1970-01-01
    • 2021-07-27
    • 1970-01-01
    相关资源
    最近更新 更多