【问题标题】:Why is this.substring(index) not working?为什么 this.substring(index) 不起作用?
【发布时间】:2018-10-30 22:06:06
【问题描述】:

下面是来自How do I replace a character at a particular index in JavaScript?的自定义String方法

String.prototype.replaceAt = function(index, replacement) {
    return this.substring(0, index) + replacement + this.substring(index + replacement.length);
}

我不希望替换来替换进行中的字符,所以我将其更改为

String.prototype.replaceAt = function(index, replacement) {
    return this.substring(0, index) + replacement + this.substring(index);
}

我用它来用 '%23' 替换 '#' 因为否则浏览器不理解链接会给出 404 错误(我在 localhost 服务器上对此进行编程)。 我的fileNames 数组看起来像

const fileNames = [
    ["template.html", "first.php", "second.php", "comments.php", "predefined.php", "strings.php", "concat.php", 
    "numbers.php", "constants.php", "quotes.php"],
    ["form.html", "handle_form #1.php", "handle_form #2.php", "handle_form #3.php"],
    [""],
    [""],
    [],
    [],
];

然后我循环遍历二维数组。最后,我用另一个循环遍历 fileNames 中的每个字符串。如果以下代码被注释掉,它工作正常,但代码完成的任务没有执行。

        for (let k = 0; k < fileNames[i][j].length; k++) {
            if (fileNames[i][j][k] == '#') {
                fileNames[i][j] = fileNames[i][j].replaceAt(k, '%23');
            }
        }
    }
}

问题是,当我将 index + replacement.length 更改为 index 时,页面停止加载,并出现一个弹出窗口,提示页面无响应。为什么会这样?我如何解决它?

【问题讨论】:

  • 你能用你找到的原始解决方案澄清问题吗?
  • “问题是,当我将 index + replacement.length 更改为 index 时,页面停止加载,并出现一个弹出窗口,提示页面无响应。”
  • 抱歉不清楚。我指的是改变它的原因。
  • 哦,改变它的原因是这些是链接。在 URL 中,它不会自动将“#”编码为“%23”,所以我必须自己做。无论哪种方式,它都会返回一个 404。例如,在 handle_form #1.php 中它必须更改为 handle_form%20%231.php 否则它会更改为 handle_form%20%23php.我不希望它替换 '1' 和 '.'
  • 我明白了,这是有道理的。对不起。

标签: javascript substring


【解决方案1】:

代码导致无限循环,因为您的错误版本 replaceAt 只是在每个 # 字符之前插入所需的子字符串。这意味着代码在处理字符串时,总是会在更远的几个字符处找到另一个#,因此循环变得无限并阻塞浏览器。

我相信你的意思是改用这个:

String.prototype.replaceAt = function(index, replacement) {
    return this.substring(0, index) + replacement + this.substring(index + 1);
}

(注意+ 1 - 这是唯一的变化!)

【讨论】:

  • 感谢 Robin Zigmond 的回答!
【解决方案2】:

您当前的逻辑只是将# 移动到字符串更远的位置,从而导致无限循环:

String.prototype.replaceAt = function(index, replacement) {
    return this.substring(0, index) + replacement + this.substring(index);
}
console.log('foo#bar'.replaceAt(3, 'baz'));

虽然不是自定义的replace 函数,为什么不直接使用内置的.replace?使用全局正则表达式匹配#s,并替换为'%23'。例如:

const fileNames = [
    ["template.html", "first.php", "second.php", "comments.php", "predefined.php", "strings.php", "concat.php", 
    "numbers.php", "constants.php", "quotes.php"],
    ["form.html", "handle_form #1.php", "handle_form #2.php", "handle_form #3.php"],
    [""],
    [""],
    [],
    [],
];
const fixedFileNames = fileNames.map((arr) => (
  arr.map((str) => str.replace(/#/g, '%23'))
));
console.log(fixedFileNames);

数组方法通常比 for 循环更好用 - 无需手动迭代,更好的抽象。

【讨论】:

  • 感谢CertainPerformance 的回答!我没有这样做,因为在嵌套的 for 循环中还有其他任务正在完成。这需要准确地放在它们之间。
  • 如果是字符串操作,您可以可能使用正则表达式进行操作 - 正则表达式在适当的情况下是一种极其强大且简洁的工具。
  • 我同意正则表达式非常强大,显然stackoverflow.com/questions/51996320/… 在这里回答了我的问题。我制作一个 JSFiddle 怎么样,你可以在上下文中查看我的代码和目标,看看是否有 方法?
  • 当然,我很乐意看看
【解决方案3】:

一般的事情,然后解决。

  1. 您应该使用浏览器的开发人员工具来查看实际错误是什么,然后将其发布。
  2. 通常不赞成将东西附加到内置对象类型上。我建议使用独立函数。

实际解决方案:您发布的代码是插入,而不是替换:它留在哈希中。然后,因为你要离开它,循环再次“找到”它并永远运行。试试这个:

String.prototype.replaceAt = function(index, replacement) {
    return this.substring(0, index) + replacement + this.substring(index + numberOfCharsToOmit);
}

并适当地添加一个数字。

【讨论】:

  • 感谢安德鲁·里奇韦的回答!在我看来,是使用全局函数还是向内置对象类型添加方法是值得商榷的。这也是本地的,我用它来组织我的 PHP 文件,我是从一本教我如何用 php 和 mysql 编程的书中编码的。它永远不会在 GitHub 上发布、公开查看或使用其他库(我喜欢纯 JavaScript)。另外,由于页面没有加载,我看不到错误。我尝试了console.log,它看起来很好,直到我在return语句中实际执行它。
【解决方案4】:

嗯,不喜欢这样改变字符串原型。

如果您的目标是对哈希字符进行编码,为什么不使用:

encodeURIComponent("#")

输出:“%23”

【讨论】:

  • 输出不会是 %23 因为“”是 %20 而“#”是 %23
  • 我必须将它插入到 .replaceAt() 方法调用中的相同位置,它会更长。
猜你喜欢
  • 2012-02-29
  • 1970-01-01
  • 2013-02-13
  • 2011-11-24
  • 1970-01-01
相关资源
最近更新 更多