日期:2014-05-16 浏览次数:20542 次
?
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];
resul