519

当使用 return 语句将字符串传递给函数时,如何在 JavaScript 中就地反转字符串,而不使用内置函数(.reverse().charAt())?

4

58 回答 58

865

只要您处理简单的 ASCII 字符,并且乐于使用内置函数,这将起作用:

function reverse(s){
    return s.split("").reverse().join("");
}

如果您需要支持 UTF-16 或其他多字节字符的解决方案,请注意此函数将提供无效的 unicode 字符串或看起来很有趣的有效字符串。您可能要考虑这个答案

[...s] 是 Unicode 感知的,一个小的编辑给出:-

function reverse(s){
    return [...s].reverse().join("");
}
于 2009-06-06T04:34:34.393 回答
426

以下技术(或类似技术)通常用于在 JavaScript 中反转字符串:

// Don’t use this!
var naiveReverse = function(string) {
    return string.split('').reverse().join('');
}

事实上,到目前为止发布的所有答案都是这种模式的变体。但是,这种解决方案存在一些问题。例如:

naiveReverse('foo  bar');
// → 'rab �� oof'
// Where did the `` symbol go? Whoops!

如果您想知道为什么会发生这种情况,请阅读 JavaScript 的内部字符编码。(TL;DR:是一个星体符号,JavaScript 将其公开为两个独立的代码单元。)

但还有更多:

// To see which symbols are being used here, check:
// http://mothereff.in/js-escapes#1ma%C3%B1ana%20man%CC%83ana
naiveReverse('mañana mañana');
// → 'anãnam anañam'
// Wait, so now the tilde is applied to the `a` instead of the `n`? WAT.

测试字符串反向实现的好字符串如下

'foo  bar mañana mañana'

为什么?因为它包含一个星体符号 ( )(在 JavaScript 中由代理对表示)和一个组合标记(最后一个mañana实际上由两个符号组成:U+006E LATIN SMALL LETTER N 和 U+0303 COMBINING TILDE)。

代理对出现的顺序不能颠倒,否则星体符号将不再出现在“颠倒的”字符串中。这就是您��在上一个示例的输出中看到这些标记的原因。

组合标记始终应用于前一个符号,因此您必须将两个主要符号(U+006E LATIN SMALL LETTER N)视为一个整体的组合标记(U+0303 COMBINING TILDE)。颠倒它们的顺序将导致组合标记与字符串中的另一个符号配对。这就是示例输出使用而不是ñ.

希望这可以解释为什么到目前为止发布的所有答案都是错误的。


为了回答您最初的问题——如何[正确] 在 JavaScript 中反转字符串——我编写了一个小型 JavaScript 库,它能够识别 Unicode 字符串反转。它没有我刚才提到的任何问题。该库称为Esrever;它的代码在 GitHub 上,几乎可以在任何 JavaScript 环境中运行。它带有一个 shell 实用程序/二进制文件,因此您可以根据需要轻松地从终端反转字符串。

var input = 'foo  bar mañana mañana';
esrever.reverse(input);
// → 'anañam anañam rab  oof'

至于“就地”部分,请参阅其他答案。

于 2013-05-27T15:47:38.517 回答
103
String.prototype.reverse_string=function() {return this.split("").reverse().join("");}

或者

String.prototype.reverse_string = function() {
    var s = "";
    var i = this.length;
    while (i>0) {
        s += this.substring(i-1,i);
        i--;
    }
    return s;
}
于 2009-06-06T04:18:50.147 回答
91

详细分析和反转字符串的十种不同方法及其性能细节。

http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/

这些实现的性能:

每个浏览器的最佳执行实现

  • Chrome 15 - 实现 1 和 6
  • Firefox 7 - 实施 6
  • IE 9 - 实施 4
  • 歌剧 12 - 实施 9

以下是这些实现:

实施1:

function reverse(s) {
  var o = '';
  for (var i = s.length - 1; i >= 0; i--)
    o += s[i];
  return o;
}

实施2:

function reverse(s) {
  var o = [];
  for (var i = s.length - 1, j = 0; i >= 0; i--, j++)
    o[j] = s[i];
  return o.join('');
}

实施3:

function reverse(s) {
  var o = [];
  for (var i = 0, len = s.length; i <= len; i++)
    o.push(s.charAt(len - i));
  return o.join('');
}

实施4:

function reverse(s) {
  return s.split('').reverse().join('');
}

实施5:

function reverse(s) {
  var i = s.length,
      o = '';
  while (i > 0) {
    o += s.substring(i - 1, i);
    i--;
  }
  return o;
}

实施6:

function reverse(s) {
  for (var i = s.length - 1, o = ''; i >= 0; o += s[i--]) { }
  return o;
}

实施 7:

function reverse(s) {
  return (s === '') ? '' : reverse(s.substr(1)) + s.charAt(0);
}

实施8:

function reverse(s) {
  function rev(s, len, o) {
    return (len === 0) ? o : rev(s, --len, (o += s[len]));
  };
  return rev(s, s.length, '');
}

实施 9:

function reverse(s) {
  s = s.split('');
  var len = s.length,
      halfIndex = Math.floor(len / 2) - 1,
      tmp;
 

     for (var i = 0; i <= halfIndex; i++) {
        tmp = s[len - i - 1];
        s[len - i - 1] = s[i];
        s[i] = tmp;
      }
      return s.join('');
    }

实施 10

function reverse(s) {
  if (s.length < 2)
    return s;
  var halfIndex = Math.ceil(s.length / 2);
  return reverse(s.substr(halfIndex)) +
         reverse(s.substr(0, halfIndex));
}

实施 11

var reverser  = function(str){
let string = str.split('');

    for(i=0;i<string.length;i++){
        debugger;
        string.splice(i,0,string.pop());
    
    } 
    console.log(string.join())
}
reverser('abcdef')
于 2014-10-28T14:31:23.837 回答
62

整个“将字符串反转到位”是一个过时的 C 程序员面试问题,被他们面试的人(也许是为了报复?)会问。不幸的是,“就地”部分不再起作用,因为几乎所有托管语言(JS、C# 等)中的字符串都使用不可变字符串,从而破坏了在不分配任何新内存的情况下移动字符串的整个想法。

虽然上述解决方案确实反转了一个字符串,但它们不会在不分配更多内存的情况下这样做,因此不满足条件。您需要直接访问分配的字符串,并且能够操纵其原始内存位置以便能够将其反转到位。

就个人而言,我真的很讨厌这类面试问题,但遗憾的是,我相信我们会在未来几年继续看到它们。

于 2010-07-14T04:44:21.893 回答
45

首先,使用Array.from()将字符串转为数组,然后Array.prototype.reverse()将数组反转,然后Array.prototype.join()将其变回字符串。

const reverse = str => Array.from(str).reverse().join('');
于 2016-04-10T04:04:12.663 回答
29

.split('')在 ECMAScript 6 中,您可以在不使用split 方法的情况下更快地反转字符串,使用扩展运算符如下:

var str = [...'racecar'].reverse().join('');
于 2015-12-24T00:39:24.773 回答
22

好像我迟到了3年...

不幸的是,您不能像已经指出的那样。请参阅JavaScript 字符串是不可变的吗?我需要 JavaScript 中的“字符串生成器”吗?

您可以做的下一个最好的事情是创建一个“视图”或“包装器”,它接受一个字符串并重新实现您正在使用的字符串 API 的任何部分,但假装字符串是颠倒的。例如:

var identity = function(x){return x};

function LazyString(s) {
    this.original = s;

    this.length = s.length;
    this.start = 0; this.stop = this.length; this.dir = 1; // "virtual" slicing
    // (dir=-1 if reversed)

    this._caseTransform = identity;
}

// syntactic sugar to create new object:
function S(s) {
    return new LazyString(s);
}

//We now implement a `"...".reversed` which toggles a flag which will change our math:

(function(){ // begin anonymous scope
    var x = LazyString.prototype;

    // Addition to the String API
    x.reversed = function() {
        var s = new LazyString(this.original);

        s.start = this.stop - this.dir;
        s.stop = this.start - this.dir;
        s.dir = -1*this.dir;
        s.length = this.length;

        s._caseTransform = this._caseTransform;
        return s;
    }

//We also override string coercion for some extra versatility (not really necessary):

    // OVERRIDE STRING COERCION
    //   - for string concatenation e.g. "abc"+reversed("abc")
    x.toString = function() {
        if (typeof this._realized == 'undefined') {  // cached, to avoid recalculation
            this._realized = this.dir==1 ?
                this.original.slice(this.start,this.stop) : 
                this.original.slice(this.stop+1,this.start+1).split("").reverse().join("");

            this._realized = this._caseTransform.call(this._realized, this._realized);
        }
        return this._realized;
    }

//Now we reimplement the String API by doing some math:

    // String API:

    // Do some math to figure out which character we really want

    x.charAt = function(i) {
        return this.slice(i, i+1).toString();
    }
    x.charCodeAt = function(i) {
        return this.slice(i, i+1).toString().charCodeAt(0);
    }

// Slicing functions:

    x.slice = function(start,stop) {
        // lazy chaining version of https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/slice

        if (stop===undefined)
            stop = this.length;

        var relativeStart = start<0 ? this.length+start : start;
        var relativeStop = stop<0 ? this.length+stop : stop;

        if (relativeStart >= this.length)
            relativeStart = this.length;
        if (relativeStart < 0)
            relativeStart = 0;

        if (relativeStop > this.length)
            relativeStop = this.length;
        if (relativeStop < 0)
            relativeStop = 0;

        if (relativeStop < relativeStart)
            relativeStop = relativeStart;

        var s = new LazyString(this.original);
        s.length = relativeStop - relativeStart;
        s.start = this.start + this.dir*relativeStart;
        s.stop = s.start + this.dir*s.length;
        s.dir = this.dir;

        //console.log([this.start,this.stop,this.dir,this.length], [s.start,s.stop,s.dir,s.length])

        s._caseTransform = this._caseTransform;
        return s;
    }
    x.substring = function() {
        // ...
    }
    x.substr = function() {
        // ...
    }

//Miscellaneous functions:

    // Iterative search

    x.indexOf = function(value) {
        for(var i=0; i<this.length; i++)
            if (value==this.charAt(i))
                return i;
        return -1;
    }
    x.lastIndexOf = function() {
        for(var i=this.length-1; i>=0; i--)
            if (value==this.charAt(i))
                return i;
        return -1;
    }

    // The following functions are too complicated to reimplement easily.
    // Instead just realize the slice and do it the usual non-in-place way.

    x.match = function() {
        var s = this.toString();
        return s.apply(s, arguments);
    }
    x.replace = function() {
        var s = this.toString();
        return s.apply(s, arguments);
    }
    x.search = function() {
        var s = this.toString();
        return s.apply(s, arguments);
    }
    x.split = function() {
        var s = this.toString();
        return s.apply(s, arguments);
    }

// Case transforms:

    x.toLowerCase = function() {
        var s = new LazyString(this.original);
        s._caseTransform = ''.toLowerCase;

        s.start=this.start; s.stop=this.stop; s.dir=this.dir; s.length=this.length;

        return s;
    }
    x.toUpperCase = function() {
        var s = new LazyString(this.original);
        s._caseTransform = ''.toUpperCase;

        s.start=this.start; s.stop=this.stop; s.dir=this.dir; s.length=this.length;

        return s;
    }

})() // end anonymous scope

演示:

> r = S('abcABC')
LazyString
  original: "abcABC"
  __proto__: LazyString

> r.charAt(1);       // doesn't reverse string!!! (good if very long)
"B"

> r.toLowerCase()    // must reverse string, so does so
"cbacba"

> r.toUpperCase()    // string already reversed: no extra work
"CBACBA"

> r + '-demo-' + r   // natural coercion, string already reversed: no extra work
"CBAcba-demo-CBAcba"

踢球者——以下是通过纯数学就地完成的,每个角色只访问一次,并且只有在必要时才访问:

> 'demo: ' + S('0123456789abcdef').slice(3).reversed().slice(1,-1).toUpperCase()
"demo: EDCBA987654"

> S('0123456789ABCDEF').slice(3).reversed().slice(1,-1).toLowerCase().charAt(3)
"b"

如果应用于非常大的字符串,如果您只取其中相对较小的一部分,这会产生显着的节省。

这是否值得(在大多数编程语言中像复制一样反转)在很大程度上取决于您的用例以及您重新实现字符串 API 的效率。例如,如果您只想进行字符串索引操作,或者取小slices 或substrs,这将为您节省空间和时间。但是,如果您计划打印大的反向切片或子字符串,则节省的成本可能确实很小,甚至比完成完整副本还要糟糕。您的“反转”字符串也将没有 type string,尽管您可以通过原型制作来伪造它。

上面的演示实现创建了一个 ReversedString 类型的新对象。它是原型化的,因​​此相当高效,几乎不需要工作和空间开销(原型定义是共享的)。这是一个涉及延迟切片的惰性实现。每当您执行类似.sliceor的函数.reversed时,它都会执行索引数学运算。最后,当您提取数据时(通过隐式调用.toString()or.charCodeAt(...)或其他东西),它将以“智能”方式应用这些数据,尽可能少地触及数据。

注意:上述字符串 API 是一个示例,可能无法完美实现。您也可以只使用您需要的 1-2 个函数。

于 2012-03-07T11:47:53.700 回答
16

有很多方法可以在 JavaScript 中反转字符串。我正在记下我喜欢的三种方式。

方法一:使用反向功能:

function reverse(str) {
  return str.split('').reverse().join('');
}

方法2:循环字符:

function reverse(str) {
  let reversed = '';

  for (let character of str) {
    reversed = character + reversed;
  }

  return reversed;
}

方法3:使用reduce函数:

function reverse(str) {
  return str.split('').reduce((rev, char) => char + rev, '');
}

我希望这有帮助 :)

于 2019-03-08T05:21:13.607 回答
15

使用扩展语法的清晰方式:

const reverseString = str => [...str].reverse().join('');

console.log(reverseString('ABC'));

于 2020-10-01T00:03:59.147 回答
11

在一次采访中,我被要求在不使用任何变量或本地方法的情况下反转字符串。这是我最喜欢的实现:

function reverseString(str) {
    return str === '' ? '' : reverseString(str.slice(1)) + str[0];
}
于 2015-02-10T20:42:46.473 回答
11

有多种方法可以做到这一点,您可以检查以下内容,

1.传统的for循环(递增):

function reverseString(str){
        let stringRev ="";
        for(let i= 0; i<str.length; i++){
            stringRev = str[i]+stringRev;
        }
        return stringRev;
}
alert(reverseString("Hello World!"));

2.传统的for循环(递减):

function reverseString(str){
    let revstr = "";
    for(let i = str.length-1; i>=0; i--){
        revstr = revstr+ str[i];
    }
    return revstr;
}
alert(reverseString("Hello World!"));

3.使用for-of循环

function reverseString(str){
    let strn ="";
    for(let char of str){
        strn = char + strn;
    }
    return strn;
}
alert(reverseString("Get well soon"));

4.使用forEach/高阶数组方法:

function reverseString(str){

  let revSrring = "";
  str.split("").forEach(function(char){
    
    revSrring = char + revSrring;
  
  });
  return revSrring;
}
alert(reverseString("Learning JavaScript"));

5、ES6标准:

function reverseString(str){

  let revSrring = "";
  str.split("").forEach(char => revSrring = char + revSrring);
  return revSrring;
}
alert(reverseString("Learning JavaScript"));

6.最新方式:

function reverseString(str){

  return str.split("").reduce(function(revString, char){
       return char + revString;
  }, "");
 
}

alert(reverseString("Learning JavaScript"));

7.您还可以使用以下方法获得结果,

function reverseString(str){

  return str.split("").reduce((revString, char)=> char + revString, "");
 
}
alert(reverseString("Learning JavaScript"));

于 2018-08-08T16:20:51.147 回答
8

在 ES6 中,您还有一个选择

function reverseString (str) {
  return [...str].reverse().join('')
}

reverseString('Hello');
于 2018-01-15T04:52:35.143 回答
6

这是我认为最简单的方法

var reverse = function(str) {
    var arr = [];
    
    for (var i = 0, len = str.length; i <= len; i++) {
        arr.push(str.charAt(len - i))
    }

    return arr.join('');
}

console.log(reverse('I want a '));

于 2011-08-09T14:03:41.263 回答
6
var str = 'sample string';
[].map.call(str, function(x) {
  return x;
}).reverse().join('');

或者

var str = 'sample string';
console.log(str.split('').reverse().join(''));

// 输出:'gnirts elpmas'

于 2015-07-04T12:27:24.507 回答
6

如果您不想使用任何内置功能。尝试这个

var string = 'abcdefg';
var newstring = '';

for(let i = 0; i < string.length; i++){
    newstring = string[i] += newstring;
}

console.log(newstring);
于 2017-09-21T10:29:47.107 回答
5

我知道这是一个已经得到很好回答的老问题,但是为了我自己的乐趣,我编写了以下反向函数,并认为我会分享它以防它对其他人有用。它处理代理对和组合标记:

function StringReverse (str)
{
  var charArray = [];
  for (var i = 0; i < str.length; i++)
    {
      if (i+1 < str.length)
        {
          var value = str.charCodeAt(i);
          var nextValue = str.charCodeAt(i+1);
          if (   (   value >= 0xD800 && value <= 0xDBFF
                  && (nextValue & 0xFC00) == 0xDC00) // Surrogate pair)
              || (nextValue >= 0x0300 && nextValue <= 0x036F)) // Combining marks
            {
              charArray.unshift(str.substring(i, i+2));
              i++; // Skip the other half
              continue;
            }
        }

      // Otherwise we just have a rogue surrogate marker or a plain old character.
      charArray.unshift(str[i]);
    }

  return charArray.join('');
}

Mathias、Punycode 和其他各种参考资料的所有道具,用于向我介绍 JavaScript 中字符编码的复杂性。

于 2013-06-28T21:43:39.020 回答
5

你不能string在原地反转 a 但你可以使用这个:

String.prototype.reverse = function() {
    return this.split("").reverse().join("");
}

var s = "ABCD";
s = s.reverse();
console.log(s);

于 2021-03-30T09:38:37.260 回答
5

一个新选项是使用Intl.Segmenter它允许您在视觉字素上进行拆分(即:用户感知的字符单元,如表情符号、字符等)。Intl.Segmenter目前是第 4 阶段的提案,如果您想使用它,可以使用polyfill 。目前最新版本的 Chrome 也支持它。

reverse()如果您使用,该方法的外观如下Intl.Segmenter

const reverse = str => {
  const segmenter = new Intl.Segmenter("en", {granularity: 'grapheme'});
  const segitr = segmenter.segment(str);
  const segarr = Array.from(segitr, ({segment}) => segment).reverse();
  return segarr.join('');
}

console.log(reverse('foo  bar mañana mañana')); // anañam anañam rab  oof
console.log(reverse('This  emoji is happy')); // yppah si ijome  sihT
console.log(reverse('Text surrogate pair  composite pair möo varient selector ❤️ & ZWJ ‍‍')); // ‍‍ JWZ & ❤️ rotceles tneirav oöm riap etisopmoc  riap etagorrus txeT

上面通过它们的视觉字素创建了一个segmenter分割/分割字符串。使用字符串输入调用.segment()segmenter然后返回一个迭代器,该迭代器生成形式为 的对象{segment, index, input, isWordLike}。该segment对象的键包含字符串段(即:单个字素)。要将迭代器转换为数组,我们Array.from()在迭代器上使用并提取分段字素,可以用 反转.reverse()。最后,我们使用.join()


您还可以尝试另一种选择,它比 Intl.Segmenter 具有更好的浏览器支持,但不是防弹的:

const reverse = str => Array.from(str.normalize('NFC')).reverse().join('');

这有助于处理由多个代码点和代码单元组成的字符。正如在其他答案中所指出的,在诸如'foo bar mañana mañana'. 这是一个由两个代码单元组成的代理对,最后一个是由两个 Unicode 字符组成的复合对组成一个字素 ( n+ ̃= )。

为了反转每个字符,您可以使用.reverse()Array 原型中的方法。正如.reverse()在数组上使用的那样,首先要做的是将字符串转换为字符数组。通常,.split('')用于此任务,但是,这会拆分由多个代码单元组成的代理对(如先前的答案中所示):

>> ''.split('')
>> `["�&quot;, "�&quot;]`

相反,如果您调用String.prototype's Symbol.iterator方法,那么您将能够在数组中保留代理对,因为它会迭代代码点而不是字符串的代码单元:

>> [...'']
>> [""]

接下来要处理的是字符串中的任何复合字符。由两个或多个代码点组成的字符在迭代时仍将被拆分:

>> [...'ö']   
>> ["o", "̈"]

以上将基本字符 (o) 与分叉分离,这不是所需的行为。这是因为它是字符的分解版本,由多个代码点组成。为了解决这个问题,您可以使用 ES6 中引入的字符串方法,称为String.prototype.normalize(). 通过使用“NFC”作为参数,此方法可以将多个代码点组合成其组合的规范形式。这允许我们将分解的字符(o +组合分音符号)转换为仅包含一个代码点的预组合形式ö带有分音符号的拉丁小写字母 o )。调用.normalize()with"NFC"因此尝试在可能的情况下用单个代码点替换多个代码点. 这允许由两个代码点组成的字素用一个代码点表示。

>> [...'ö'.normalize('NFC')]   
>> ["ö"]

normalize('NFC')产生一个字符时,它可以在其他字符中安全地反转。将扩展语法和规范化放在一起,您可以成功地反转字符串,例如:

const reverse = str => Array.from(str.normalize('NFC')).reverse().join('');

console.log(reverse('foo  bar mañana mañana'));
console.log(reverse('This  emoji is happy'));

在少数情况下,上述规范化+迭代会失败。例如,字符 ❤️(重黑心 ❤️)由两个代码点组成。第一个是心形,后者是变体选择器 16 (U+FE0F),用于定义前一个字符的字形变体。其他角色也会产生类似的问题。

要注意的另一件事是ZWJ(零宽度连接符)字符,您可以在某些脚本中找到它,包括表情符号。例如,表情符号 ‍‍ 由男人、女人和男孩表情符号组成,每个表情符号由 ZWJ 分隔。上面的归一化+迭代方法也不会考虑到这一点。

因此,使用Intl.Segmenter是这两种方法的更好选择。目前,Chrome 也有自己的特定分段 API,称为Intl.v8BreakIterator。这个分段 API 是非标准的,Chrome 只是简单地实现了一些东西。因此,它可能会发生变化,并且不适用于大多数浏览器,因此不建议使用。但是,如果您很好奇,可以这样做:

const reverse = str => {
  const iterator = Intl.v8BreakIterator(['en'], {type: 'character'});
  iterator.adoptText(str);
  const arr = [];
  let pos = iterator.first();
  while (pos !== -1) {
    const current = iterator.current();
    const nextPos = iterator.next();
    if (nextPos === -1) break;
    const slice = str.slice(current, nextPos);
    arr.unshift(slice);
  }
  return arr.join("");
}

console.log(reverse('foo  bar mañana mañana')); // anañam anañam rab  oof
console.log(reverse('This  emoji is happy')); // yppah si ijome  sihT
console.log(reverse('Text surrogate pair  composite pair möo varient selector ❤️ & ZWJ ‍‍')); // ‍‍ JWZ & ❤️ rotceles tneirav oöm riap etisopmoc  riap etagorrus txeT

于 2020-02-04T11:53:41.710 回答
5

你不能因为 JS 字符串是不可变的。短的非就地解决方案

[...str].reverse().join``

let str = "Hello World!";
let r = [...str].reverse().join``;
console.log(r);

于 2019-07-24T05:32:12.910 回答
3
于 2017-01-09T15:01:06.430 回答
2

我认为 String.prototype.reverse 是解决这个问题的好方法;代码如下;

String.prototype.reverse = function() {
  return this.split('').reverse().join('');
}

var str = 'this is a good example for string reverse';
str.reverse();
-> "esrever gnirts rof elpmaxe doog a si siht";
于 2014-01-02T07:31:07.753 回答
2

真正的答案是:你不能原地反转它,但你可以创建一个反转的新字符串。

就像玩递归一样:有时当你去面试时,面试官可能会问你如何使用递归来做到这一点,我认为“首选答案”可能是“我宁愿不这样做递归,因为它很容易导致堆栈溢出”(因为它O(n)不是O(log n)。如果是O(log n),那么堆栈溢出是相当困难的——堆栈级别为 32 可以处理 40 亿个项目,因为 2 ** 32 是 4294967296。但如果是O(n),那么很容易导致堆栈溢出。

有时候面试官还是会问你,“作为一个练习,你为什么不还是用递归来写呢?” 这里是:

String.prototype.reverse = function() {
    if (this.length <= 1) return this;
    else return this.slice(1).reverse() + this.slice(0,1);
}

测试运行:

var s = "";
for(var i = 0; i < 1000; i++) {
    s += ("apple" + i);
}
console.log(s.reverse());

输出:

999elppa899elppa...2elppa1elppa0elppa

为了尝试让堆栈溢出,我更改100010000在 Google Chrome 中,它报告:

RangeError: Maximum call stack size exceeded
于 2013-06-23T17:09:40.083 回答
2

字符串本身是不可变的,但您可以使用以下代码轻松创建反向副本:

function reverseString(str) {

  var strArray = str.split("");
  strArray.reverse();

  var strReverse = strArray.join("");

  return strReverse;
}

reverseString("hello");
于 2016-05-11T01:01:59.910 回答
2
//es6
//array.from
const reverseString = (string) => Array.from(string).reduce((a, e) => e + a);
//split
const reverseString = (string) => string.split('').reduce((a, e) => e + a); 

//split problem
"".split('')[0] === Array.from("")[0] // "�" === "" => false
"".split('')[0] === Array.from("")[0] // "�" === "" => false
于 2017-05-01T04:48:42.337 回答
2

使用内置函数反转字符串

function reverse(str) {
  // Use the split() method to return a new array
  //  Use the reverse() method to reverse the new created array
  // Use the join() method to join all elements of the array into a string
  return str.split("").reverse().join("");
}
console.log(reverse('hello'));


在没有助手的情况下反转字符串

function reversedOf(str) {
  let newStr = '';
  for (let char of str) {
    newStr = char + newStr
    // 1st round: "h" + "" = h, 2nd round: "e" + "h" = "eh" ... etc. 
    // console.log(newStr);
  }
  return newStr;
}
console.log(reversedOf('hello'));

于 2020-01-31T16:16:29.707 回答
1
function reverseString(string) {
    var reversedString = "";
    var stringLength = string.length - 1;
    for (var i = stringLength; i >= 0; i--) {
        reversedString += string[i];
    }
    return reversedString;
}
于 2009-06-06T04:25:47.900 回答
1
var str = "my name is saurabh ";
var empStr='',finalString='';
var chunk=[];
function reverse(str){
var i,j=0,n=str.length;
    for(i=0;i<n;++i){
        if(str[i]===' '){
            chunk[j]=empStr;
            empStr = '';
            j++;
        }else{
            empStr=empStr+str[i];
        }
    }
    for(var z=chunk.length-1;z>=0;z--){
        finalString = finalString +' '+ chunk[z];
        console.log(finalString);
    }
    return true;
}
reverse(str);
于 2015-02-11T09:28:11.990 回答
1

使用数组函数,

String.prototype.reverse = function(){
    return [].reduceRight.call(this, function(last, secLast){return last + secLast});
}
于 2014-08-21T18:11:16.700 回答
1

这是一个不使用 Array.prototype.reverse 的基本 ES6 不可变示例:

// :: reverse = String -> String
const reverse = s => [].reduceRight.call(s, (a, b) => a + b)

console.log(reverse('foo')) // => 'oof'
console.log(reverse('bar')) // => 'rab'
console.log(reverse('foo-bar')) // => 'rab-oof'

于 2015-06-11T23:04:35.013 回答
1

在 JavaScript 中反转字符串的最佳方法

1)Array.reverse:

你可能在想,等等,我以为我们正在反转一个字符串,你为什么要使用 Array.reverse 方法。使用 String.split 方法,我们将字符串转换为字符数组。然后我们颠倒数组中每个值的顺序,最后我们使用 Array.join 方法将数组转换回字符串。

function reverseString(str) {
    return str.split('').reverse().join('');
}
reverseString('dwayne');

2)递减while循环:

尽管相当冗长,但该解决方案确实比解决方案一具有优势。您不是在创建一个数组,而只是根据源字符串中的字符连接一个字符串。

从性能的角度来看,这可能会产生最好的结果(尽管未经测试)。不过,对于极长的字符串,性能提升可能会超出预期。

function reverseString(str) {
    var temp = '';
    var i = str.length;

    while (i > 0) {
        temp += str.substring(i - 1, i);
        i--;
    }


    return temp;
}
reverseString('dwayne');

3) 递归

我喜欢这个解决方案的简单明了。您可以清楚地看到 String.charAt 和 String.substr 方法被用于通过每次调用自身来传递不同的值,直到字符串为空,其中三元组只会返回一个空字符串,而不是使用递归调用自身. 这可能会产生第二个解决方案之后的第二个最佳性能。

function reverseString(str) {
    return (str === '') ? '' : reverseString(str.substr(1)) + str.charAt(0);
}
reverseString('dwayne');
于 2015-06-29T09:31:34.077 回答
1

好的,很简单,您可以创建一个带有简单循环的函数来为您执行字符串反转,而无需使用reverse()等,charAt()如下所示:

例如你有这个字符串:

var name = "StackOverflow";

创建一个这样的函数,我称之为reverseString...

function reverseString(str) {
  if(!str.trim() || 'string' !== typeof str) {
    return;
  }
  let l=str.length, s='';
  while(l > 0) {
    l--;
    s+= str[l];
  }
  return s;
}

你可以这样称呼它:

reverseString(name);

结果将是:

"wolfrevOkcatS"
于 2017-07-19T15:46:37.493 回答
1

以下是您可以用来实现字符串反转的四种最常用的方法

给定一个字符串,返回一个字符顺序相反的新字符串

多种解决方案

//reverse('apple') === 'leppa'
//reverse('hello') === 'olleh'
//reverse('Greetings!') === '!sgniteerG'

// 1. First method without using reverse function and negative for loop
function reverseFirst(str) {
    if(str !== '' || str !==undefined || str !== null) {
        const reversedStr = [];
        for(var i=str.length; i>-1; i--) {
        reversedStr.push(str[i]);
        }
    return reversedStr.join("").toString();
    }
}

// 2. Second method using the reverse function
function reverseSecond(str) {
    return str.split('').reverse().join('');
}

// 3. Third method using the positive for loop
function reverseThird(str){
    const reversedStr = [];
    for(i=0; i<str.length;i++) {
        reversedStr.push(str[str.length-1-i])
    }
    return reversedStr.join('').toString();
}

// 4. using the modified for loop ES6
function reverseForth(str) {
    const reversedStr = [];
    for(let character of str) {
        reversedStr = character + reversedStr;
    }
    return reversedStr;
}

// 5. Using Reduce function
function reverse(str) {
    return str.split('').reduce((reversed, character) => {
        return character + reversed;  
    }, '');
}
于 2018-12-17T12:42:13.820 回答
1

我自己的原始尝试...

var str = "The Car";

function reverseStr(str) {
  var reversed = "";
  var len = str.length;
  for (var i = 1; i < (len + 1); i++) {  
    reversed += str[len - i];      
  }

  return reversed;
}

var strReverse = reverseStr(str);    
console.log(strReverse);
// "raC ehT"

http://jsbin.com/bujiwo/19/edit?js,控制台,输出

于 2015-11-25T22:21:18.753 回答
1

保持干燥和简单愚蠢!

function reverse(s){
let str = s;
var reverse = '';
for (var i=str.length;i>0;i--){

    var newstr = str.substring(0,i)
    reverse += newstr.substr(-1,1)
}
return reverse;
}
于 2017-07-08T15:42:37.217 回答
1

如果您对性能和时间复杂度比较好奇,请使用此方法。在这种方法中,我将字符串分成两部分,并按长度/2 次循环迭代对其进行排序。

let str = "abcdefghijklmnopqrstuvwxyz"

function reverse(str){
let store = ""
let store2 = ""

for(let i=str.length/2;i>=0;i--){
  if(str.length%2!==0){
     store += str.charAt(i) 
  store2 += str.slice((str.length/2)+1, str.length).charAt(i)
  }else{
store += str.charAt(i-1) 
  store2 += str.slice((str.length/2), str.length).charAt(i)
  }
  
}
return store2+store
}

console.log(reverse(str))

这不是最优的,但我们可以这样想。

于 2020-06-13T14:29:12.987 回答
1

ES6

 function reverseString(str) {
     return [...str].reverse().join("");
 }

 console.log(reverseString("Hello")); // olleH
于 2021-10-04T15:00:51.333 回答
0

以下内容可能会帮助任何希望递归地反转字符串的人。在最近一次使用函数式编程风格的工作面试中被要求这样做:

var reverseStr = function(str) {
    return (str.length > 0) ? str[str.length - 1] + reverseStr(str.substr(0, str.length -   1)) : '';
};

//tests
console.log(reverseStr('setab retsam')); //master bates
于 2014-08-11T23:19:10.973 回答
0

另一个变体(它是否适用于 IE?):

String.prototype.reverse = function() {
    for (i=1,s=""; i<=this.length; s+=this.substr(-i++,1)) {}
    return s;
}

编辑:

这没有使用内置函数:

String.prototype.reverse = function() {
    for (i=this[-1],s=""; i>=0; s+=this[i--]) {}
    return s;
}

注意:this[-1] 保存字符串的长度。

但是,不可能在适当的位置反转字符串,因为对单个数组元素的分配不适用于 String 对象(受保护?)。即你可以做分配,但结果字符串不会改变。

于 2009-06-06T10:17:26.197 回答
0
function reverse_string(string)
{
var string;

var len = string.length;

var stringExp = string.split('');
var i;
for (i = len-1; i >=0;i--)
{
var result = document.write(stringExp[i]);
}

return result;
}

reverse_string("This is a reversed string");

//输出: gnirts desrever a si sihT

于 2012-06-19T13:06:44.020 回答
0

你可以试试这样的。我确信有一些重构的空间。我无法使用拆分功能。也许有人知道一种不分裂的方法。

要设置的代码,可以将其放入您的 .js 库中

使用它的代码(有客户端代码,只是因为它是在浏览器中测试的):

var sentence = "My Stack is Overflowing."
document.write(sentence.reverseLetters() + '<br />');
document.write(sentence.reverseWords() + '<br />');

片段:

String.prototype.aggregate = function(vals, aggregateFunction) {

  var temp = '';
  for (var i = vals.length - 1; i >= 0; i--) {
    temp = aggregateFunction(vals[i], temp);
  }
  return temp;
}

String.prototype.reverseLetters = function() {
  return this.aggregate(this.split(''),
    function(current, word) {
      return word + current;
    })
}

String.prototype.reverseWords = function() {
  return this.aggregate(this.split(' '),
    function(current, word) {
      return word + ' ' + current;
    })
}

var sentence = "My Stack is Overflowing."
document.write(sentence.reverseLetters() + '<br />');
document.write(sentence.reverseWords() + '<br />');

于 2009-06-06T04:54:43.433 回答
0
var str = "IAMA JavaScript Developer";
var a=str.split(''), b = a.length;
for (var i=0; i<b; i++) {
    a.unshift(a.splice(1+i,1).shift())
}
a.shift();
alert(a.join(''));
于 2011-06-17T23:43:18.693 回答
0

无需将字符串转换为数组;

String.prototype.reverse = function() {

    var ret = "";
    var size = 0;

    for (var i = this.length - 1; -1 < i; i -= size) {

        if (
          '\uD800' <= this[i - 1] && this[i - 1] <= '\uDBFF' && 
          '\uDC00' <= this[i]     && this[i]     <= '\uDFFF'
        ) {
            size = 2;
            ret += this[i - 1] + this[i];
        } else {
            size = 1;
            ret += this[i];
        }
    }

    return ret;
}

console.log('anãnam anañam' === 'mañana mañana'.reverse());

使用 Array.reverse 而不将字符转换为代码点;

String.prototype.reverse = function() {

    var array = this.split("").reverse();

    for (var i = 0; i < this.length; ++i) {

        if (
          '\uD800' <= this[i - 1] && this[i - 1] <= '\uDBFF' && 
          '\uDC00' <= this[i]     && this[i]     <= '\uDFFF'
        ) {
            array[i - 1] = array[i - 1] + array[i];
            array[i] = array[i - 1].substr(0, 1);
            array[i - 1] = array[i - 1].substr(1, 1);
        }

    }

    return array.join("");
}

console.log('anãnam anañam' === 'mañana mañana'.reverse());
于 2013-10-28T03:33:44.220 回答
0
function reverse(str){
var s = "";
for (var i = str.length - 1; i >= 0; i--){
    s += str[i];
}
return s;
};
reverse("your string comes here")
于 2014-02-14T08:45:49.030 回答
0

没有内置方法?鉴于 Javascript 中的字符串是不可变的,您可能希望使用内置方法,如 split、join 等。但是,如果没有这些方法,这里有两种方法:

function ReverseString(str) {
    var len = str.length;
    var newString = [];

    while (len--) {
        newString.push(str[len]);
    }

    return newString.join('');
}

console.log(ReverseString('amgod')) //dogma

function RecursiveStringReverse(str, len) {
    if (len === undefined)
        len = str.length - 1;

    if (len > 0)
        return str[len] + RecursiveReverse(str, --len);

    return str[len];
}

console.log(RecursiveStringReverse('Hello, world!'))// !dlrow ,olleH
于 2019-11-17T00:31:29.047 回答
0
var reverseString = function(str){ 
  let length = str.length - 1;
  str = str.split('');

  for(let i=0;i<= length;i++){
    str[length + i + 1] = str[length - i];
  }

  return str.splice(length + 1).join('');
}
于 2017-12-28T12:38:08.300 回答
0

其中一种方法也可以是在使用 split 方法后使用 reduce 方法来反转。

function reverse(str) {
    return str.split('').reduce((rev, currentChar) => currentChar + rev, '');
}
  console.log(reverse('apple'));
  console.log(reverse('hello'));
  console.log(reverse('Greetings!'));

于 2021-04-05T05:19:36.197 回答
0

添加到 String 原型是理想的(以防它被添加到核心 JS 语言中),但是您首先需要检查它是否存在,如果不存在则添加它,如下所示:

String.prototype.reverse = String.prototype.reverse || function () {
    return this.split('').reverse().join('');
};
于 2015-10-03T19:48:56.997 回答
0

为没有循环的字符串反向添加,它通过递归工作。

function reverse(y){
    if(y.length==1 || y.length == 0 ){
        return y;
    }
    return y.split('')[y.length - 1]+ reverse(y.slice(0, y.length-1));
}
console.log(reverse("Hello"));

于 2020-02-02T12:57:01.130 回答
0

    function reverse(string)
    {
    let arr = [];
    for(let char of string) {
      arr.unshift(char);
    }
    let rev = arr.join('')
    return rev
    }
    
    let result = reverse("hello")
    console.log(result)

于 2020-04-02T05:06:58.543 回答
0

应该遵循最佳实践来完成这样的事情:

(function(){
	'use strict';
	var str = "testing";
	
	//using array methods
	var arr = new Array();
	arr = str.split("");
	arr.reverse();
	console.log(arr);
	
	//using custom methods
	var reverseString = function(str){
		
		if(str == null || str == undefined || str.length == 0 ){
			return "";
		}
		
		if(str.length == 1){
			return str;
		}
		
		var rev = [];
		for(var i = 0; i < str.length; i++){
			rev[i] = str[str.length - 1 - i];
		}
		return rev;
	} 
	
	console.log(reverseString(str));
	
})();

于 2017-07-05T08:17:22.433 回答
0

我们可以从两端迭代字符串数组:开始和结束,并在每次迭代时交换。

function reverse(str) {
 let strArray = str.split("");
 let start = 0;
 let end = strArray.length - 1;

 while(start <= end) {
  let temp = strArray[start];
  strArray[start] = strArray[end];
  strArray[end] = temp;

  start++;
  end--;
 }
 return strArray.join("");
}

尽管操作的数量减少了,但它的时间复杂度仍然是 O(n),因为操作的数量仍然与输入的大小成线性关系。

参考:算法日报

于 2021-02-03T21:18:12.107 回答
0
function reverseWords(str) {
  // Go for it
  const invertirPalabra = palabra => palabra.split('').reverse().join('')
  return str.split(' ').map(invertirPalabra).join(' ')
  // con split convierto string en array de palabras, le paso ' ' 
  // que es que me lo separe por espacios
  // luego invierto cada palabra...
  // y luego con join las uno separando por espacios
}
于 2021-06-11T14:19:34.433 回答
-1
// try this simple way

const reverseStr = (str) => {
    let newStr = "";
    for (let i = str.length - 1; i >= 0; i--) {
        newStr += str[i];
    }
    return newStr;
}
console.log(reverseStr("ABCDEFGH")); //HGFEDCBA
于 2021-05-10T14:21:34.390 回答
-1
//recursive implementation
function reverse(wrd) {
  const str =wrd[0]
  if(!wrd.length) {
    return wrd
  }
  return reverse(wrd.slice(1)) + str
}
于 2021-11-30T11:16:58.233 回答
-2
word.split('').reduce((acc, curr) => curr+""+acc)
于 2019-02-12T18:01:51.197 回答
-2

我想,这对你有用

function reverse(str){
    str = str.split("").reverse().join("").split(" ").reverse().join(" ");
    console.log(str)
}
于 2015-11-09T03:45:34.120 回答
-4

原地反转字符串是不可能的,但可以在原地反转。

于 2016-01-27T04:49:04.617 回答