chrome :
以前初学java时,总是被建议多看 jdk源码可以大大增强功力,后来想把这套也搬到javascript的学习过程中,无奈发现本来应该算作javascript 基础api范畴的 String , Array ... 等都是 native code ,但现在不一样了,chrome V8
来了,我不懂他是怎么实现的
,但是 javascript 中的基础 api 都是用 javascript 自身实现的(alert(String.prototype.replace);),和 java 越来越接近了,大概由于 v8 的作者
以前就是搞jvm的,觉得这些东西还是像 java 一样作为工具包提供比较好吧。
V8 源码@google code
V8 作者的解释:
All library functions are implemented in JavaScript
Examples: Array.prototype.join, String.prototype.replace
The benefits of not implementing it inside the engine:
1.Keeps the core engine cleaner
2.Easier to change and extend
3.Capitalizes on the performance of the JavaScript compiler
One drawback is startup time ~30 ms ...(每次启动编译库代码)
启动慢的解决之道:
V8 allows saving the initial heap in a snapshot
1.Serialized form is very fast to read
2.Includes pre-compiled code for JavaScript builtins
3.Integrated in the build system and embedded directly in V8
With snapshots, the startup time is reduced to 4-8 ms
String.prorotype.replace 应该还算复杂,特别是 replacement可以为函数这个特性是java等静态没有的。
看一下String的replace的主要框架实现吧(最复杂的正则表达式 + 函数替换
),加了点注释便于理解。详见:String.js
/*
regexp 正则表达式
replace 为函数 function(match,capture1,capture2 ...){
}
*/
function StringReplaceRegExpWithFunction(subject, regexp, replace) {
//先做一次正则match,因为下面循环中需要前一次的匹配结束位置,便于写循环
var lastMatchInfo = DoRegExpExec(regexp, subject, 0);
if (IS_NULL(lastMatchInfo)) return subject;
/*
类似于Stringbuilder ,便于从subject截取指定范围子串,存在自己的数组
generate 时用常见的 join 即可。
*/
var result = new ReplaceResultBuilder(subject);
/*
如果正则表达式带g,要全部替换
*/
if (regexp.global) {
//初始上一次匹配成功位置为 0
var previous = 0;
do {
//上一次匹配位置到这次匹配成功开始位置要放在结果里
result.addSpecialSlice(previous, lastMatchInfo[CAPTURE0]);
//当前匹配成功开始位置,match.index
var startOfMatch = lastMatchInfo[CAPTURE0];
//当前匹配成功结束位置,相当于 regexp.lastIndex
previous = lastMatchInfo[CAPTURE1];
//当前匹配传给replacement函数得到替换结果加入结果集合
result.add(ApplyReplacementFunction(replace, lastMatchInfo, subject));
//如果只匹配一个字。。。相当于 regexp == /[\s\S]/
if (previous == startOfMatch) {
// 确实没越界,加入结果集合
if (previous < subject.length) {
result.addSpecialSlice(previous, previous + 1);
}
//下次就要从previous开始加入集合了。
previous++;
}
//没越界,继续分析
lastMatchInfo = (previous > subject.length)
? null
: DoRegExpExec(regexp, subject, previous);
//没有match就结束
} while (!IS_NULL(lastMatchInfo));
//最后一次匹配结束位置到字符串结尾
if (previous < subject.length) {
result.addSpecialSlice(previous, subject.length);
}
}
//不是 g 正则,简单
else {
result.addSpecialSlice(0, lastMatchInfo[CAPTURE0]);
var endOfMatch = lastMatchInfo[CAPTURE1];
result.add(ApplyReplacementFunction(replace, lastMatchInfo, subject));
result.addSpecialSlice(endOfMatch, subject.length);
}
//结果数组 join 了,比字符串简单加起来快呢。
return result.generate();
}
dean.edwards
其实早在 ie7刚发布时,大牛 dean.edwards 写了个提升ie7以下浏览器到ie7功能的 ie7.js
,其中就用javascript实现了 正则+函数替换的功能,据说ie5没有这个功能?。。。
看下 吧,很精巧的地方是 dean.edwards 直接不用正则表达式的 g exec() 功能,而是动态修改当前要匹配的字符串,减少的状态记忆(chrome 的 preivous)。
// Fix String.replace (Safari1.x/IE5.0).
//regexp.global 也不可靠?直接判断正则有没有g吧
var GLOBAL = /(g|gi)$/;
var _String_replace = String.prototype.replace;
String.prototype.replace = function(expression, replacement) {
if (typeof replacement == "function") { // Safari doesn't like functions
if (expression && expression.constructor == RegExp) {
var regexp = expression;
var global = regexp.global;
//regexp.global 也不可靠?直接判断正则有没有g吧
if (global == null) global = GLOBAL.test(regexp);
// we have to convert global RexpExps for exec() to work consistently
//很精巧,即使是g 全局的也要剥离掉 ,使得全局不全局可以很统一和谐的对待
if (global) regexp = new RegExp(regexp.source); // non-global
} else {
regexp = new RegExp(rescape(expression));
}
var match, string = this, result = "";
while (string && (match = regexp.exec(string))) {
//匹配项替换后结果以及匹配前缀放入结果
result += string.slice(0, match.index) + replacement.apply(this, match);
//这样很好,不用像chrome那样还要记录 previous 的状态,直接把要正则匹配的字符串截断。
string = string.slice(match.index + match[0].length);
//全局不全局只有这一个差别了
if (!global) break;
}
//最后一次匹配结束位置到字符串结尾
return result + string;
}
return _String_replace.apply(this, arguments);
};
比较:
chrome :
很大气,很java,效率很高
,代码基本没有利用javascript的特性,就是用java思路写javascript,
dean.edwards :
很精巧,充分利用了javascript,减少了记忆状态,并且全局不全局统一处理代码很紧凑(compact),
但是string生成比较多哦(slice ,+ 操作)
Bonus :
最简约的实现:(当然replacement不能是函数
,简约么)
String.prototype.replace = function(pattern, replacement) {
//实现split先...
return this.split(pattern).join(replacement);
};
分享到:
相关推荐
string.prototype.replaceall 用于String.prototype.replaceAll的ES Proposal规范填充程序。 如果不可用或不String.prototype.replaceAll调用其“ shim”方法对String.prototype.replaceAll进行填充。 该软件包...
根据给定文件中的代码示例,我们可以看到作者通过扩展`String.prototype`,实现了三种不同的字符串修剪方法:`Trim()`, `LTrim()`, 和 `Rtrim()`。下面将详细解析这些方法的实现原理及使用场景。 ### 1. `String....
下面将介绍通过String.prototype实现的一些JavaScript函数,包括批量替换、修剪空白字符、判断字符串开始和结束、计算字符串长度等操作。 1. ReplaceAll函数用于批量替换字符串中的字符或子串。该方法通过接收两个...
为了方便使用,这里采用扩展JavaScript原生`String`对象的方法实现,即通过扩展`String.prototype`来实现这些功能: ```javascript String.prototype.Trim = function () { return this.replace(/(^\s*)|(\s*$)/g,...
在JavaScript编程中,`String.prototype`是一个非常重要的概念,它是JavaScript内置String对象的原型对象。通过向`String.prototype`添加方法,我们能够扩展String对象的功能,从而为所有的String实例添加新的行为。...
本文主要探讨如何通过扩展`String.prototype`来实现一种新的字符串拼接方法——`format`。这种方法提供了一种更加灵活且易于维护的方式来处理字符串格式化。 #### 一、基本概念理解 在深入了解`String.prototype....
总的来说,虽然JavaScript原生不支持`String.Format`,但通过扩展`String.prototype`,我们可以创建自己的函数来实现类似的功能,以满足在JavaScript中动态生成和格式化字符串的需求。这种自定义方法不仅可以提高...
否则,行为与String.prototype.replace(regexp, newSubstr|function)匹配。 大纲 安装及使用 在浏览器中: < script src =" https://unpkg.com/union-replacer/dist/union-replacer.umd.js " /> 使用 : ...
字符串替换异步知道如何等待的“ string” .replace()函数安装$ npm install string-replace-async用法let replaceAsync = require ( "string-replace-async" ) ;await replaceAsync ( "#rebeccapurple" , / # ( \...
值得注意的是,在原生JavaScript中,ES2015标准已正式引入了String.prototype.replaceAll()方法。因此,如果在现代浏览器环境中,可以直接使用原生的replaceAll方法来执行全局替换,无需自己编写自定义方法。不过,...
类似于String.prototype.replace(),但尝试匹配要替换的子字符串的大小写。 请考虑关注该项目的作者 ,并考虑为该项目以显示您的 :red_heart: 和支持。 安装 使用安装: $ npm install --save replace-case ...
另一种是通过自定义扩展 `String.prototype` 来实现。 #### 二、使用带有全局标志 `g` 的正则表达式实现全局替换 ##### 2.1 基本原理 在JavaScript中,正则表达式的构造允许我们指定一个全局标志 `g`,这样当使用 ...
在JavaScript中,`String.prototype.replace()` 是一个非常重要的字符串方法,用于在字符串中查找匹配的模式(可以是正则表达式或子字符串)并替换它们。这个方法的使用技巧广泛,能够实现各种复杂的字符串处理需求...
JavaScript提供了多种方法来去除字符串首尾的空格,其中`LTrim`、`RTrim`和`Trim`是常用的自定义函数实现。例如: ```javascript String.prototype.LTrim = function() { return this.replace(/(^\s*)/g, ""); } ...
JavaScript中的`String.prototype.replace()`函数是一个非常实用的工具,它允许开发者在字符串中找到特定的字符或模式,并将其替换为其他字符或字符串。这个方法在前端开发、后端开发以及各种JavaScript相关的应用...
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/g,""); } ``` - **应用场景**:通常用于清理用户输入的数据,确保不会因为空白字符导致错误。 2. **`ltrim()`**:仅移除字符串开头的...
### JavaScript中的`String.prototype.replace`方法详解 #### 一、`replace`方法的基本用法 在JavaScript中,`String.prototype.replace`是一个非常重要的方法,用于替换字符串中的某些部分。其基本语法如下: ``...
源于C#中的string.Format() 代码如下: String.prototype.format = function(args) { if (arguments.length>0) { var result = this; if (arguments.length == 1 && typeof (args) == “object”) { for (var key in ...
`String.prototype.split()`函数是JavaScript中的一个关键方法,用于将字符串分割成数组,根据提供的分隔符进行切割。然而,在不同浏览器,尤其是IE浏览器的不同版本之间,这个函数的行为可能会有所差异,这给开发者...