JavaScript中奇妙的replace

1、发现问题:

今天在读require.js源代码时,不经意读到这么一段代码:

 1 //If no name, and callback is a function, then figure out if it a
 2 //CommonJS thing with dependencies.
 3 if (!deps && isFunction(callback)) {
 4     deps = [];
 5     //Remove comments from the callback string,
 6     //look for require calls, and pull them into the dependencies,
 7     //but only if there are function args.
 8     if (callback.length) {
 9         callback
10             .toString()
11             .replace(commentRegExp, '')
12             .replace(cjsRequireRegExp, function (match, dep) {
13                 deps.push(dep);
14             });
15 
16         //May be a CommonJS thing even without require calls, but still
17         //could use exports, and module. Avoid doing exports and module
18         //work though if it just needs require.
19         //REQUIRES the function to expect the CommonJS variables in the
20         //order listed below.
21         deps = (callback.length === 1 ? ['require'] : ['require', 'exports', 'module']).concat(deps);
22     }
23 }

同样,在sea.js,也读到类似的代码段:

 1 function parseDependencies(code) {
 2   var ret = []
 3 
 4   code.replace(SLASH_RE, "")
 5       .replace(REQUIRE_RE, function(m, m1, m2) {
 6         if (m2) {
 7           ret.push(m2)
 8         }
 9       })
10 
11   return ret
12 }

或许你未曾读过这两个文件,但是这不是我提及问题的重点(如果读者对此感兴趣,可以自己到github上去找源码研究),仔细看两个代码段中,都有使用到我们今天的主角——replace

看replace传入的第一个参数,恩,是我想象的东西——一个正则表达式,但是到我读到第二个参数时,我凌乱了,尽然传入的是一个函数!确实,虽然我以前知道第二个参数可以传入函数,但是奇怪的是,它为什么没有返还值呢?

2、关于replace:

在w3cschool中有这么一段定义:

语法

stringObject.replace(regexp/substr,replacement)

参数 描述

regexp/substr

必需。规定子字符串或要替换的模式的 RegExp 对象。

请注意,如果该值是一个字符串,则将它作为要检索的直接量文本模式,而不是首先被转换为 RegExp 对象。

replacement必需。一个字符串值。规定了替换文本或生成替换文本的函数。

 

很多和我一样的菜鸟大概会被这个描述所蒙蔽,其实当第二个参数传入函数时,我们不仅可以通过函数来动态生成并返还成要替换的文本,此刻的函数中的arguments对象会保存一些很重要的数据,举个小小的例子:

1 //定义一个检测“=数字”正则表达式和一个测试字符串
2 var reg = /\=(\d)/g,
3     testStr = 'a=1,b=2,c=3,d=3';
4 //调用testStr的replace函数
5 testStr.replace(reg, function () {
6     //打印arguments对象的详细信息
7     console.log(arguments);
8 });

在谷歌控制台下,可以看到如下的测试结果:


这个函数被执行了4次,每次执行都代表正则表达成功匹配到了字符子串,那么对应的每次执行的arguments对象里面又存的什么信息呢?

在这里,我们可以看到:

参数1——表示当前匹配到的结果;

参数2——表示匹配到的正则表达式的“组”(也就是当前正则表达式小括号里面内容——这里指“\d”);

参数3——表示匹配到的字符串的索引位置;

参数4——不用多说,就是源字符串自己。

其实,通过网上的搜索,最终可以找到replace最官方、最标准的用法,当然,通过一些资料的查询,这里传入函数的arguments对象,是一个“动态可伸缩的”的,因为我们所使用的正则表达式里面含有多个组,而这里仅仅只有一个组,所以我们“当且仅当”可以看到第二个参数。

那么,我们把正则表达式换成这样又如何呢?

1 //定义一个检测“=数字”正则表达式和一个测试字符串
2 var reg = /\=\d/g,
3     testStr = 'a=1,b=2,c=3,d=3';
4 //调用testStr的replace函数
5 testStr.replace(reg, function () {
6     //打印arguments对象的详细信息
7     console.log(arguments);
8 });

显然,如我们所愿了,我们并没有捕获到等号后面的数字:

3、运用场景:

利用正则表达式的组定义,可以方便地利用这个特性,快速地找到你想要的信息,这是解决js正则表达式不支持“零宽断言”的一个巧妙的方法,正如我给大家举的例子,我们大多时候在验证的时候,想匹配到“=”后面的数字,而不是“=”+[数字]。

回归我们文章开头的代码,了解过AMD编程的童鞋大概都知道CommonJs编程范式,require.js和sea.js在找寻一个模块的工厂函数内的依赖模块id时,将工厂函数转换成了string,并且替换掉注释之后,利用我们今天说所的这个特性,把工厂函数里面的类似require('xxx/xxx')的代码侦测出来,提取出模块id——‘xxx/xxx’,并且存到数组中,最终来形成这个模块依赖其他模块的id集合。(如果不知所云,请点击这里吧https://github.com/amdjs/amdjs-api/wiki/AMD)

转载于:https://www.cnblogs.com/wuchu/p/3405984.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/433002.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python3 x和python2 x区别_Python知识:Python 3.x和2.x版本的使用区别

使用Python时都需要安装相应的版本,不同的版本适用性也不一样。今天从除法算子、打印功能、Unicode、Xrange、错误处理、未来模块方面看看Python2.x和Python3.x之间的区别。除法算子在移植代码或在python2.x中执行python3.x代码时,要注意整数除法的更改&…

select EINTR

实验环境:ubuntuKylin 13.10 在程序里同时有select和定时器, select 会被定时器产生的EINTR中断 在定时器的设置中增加了SA_RESTART和sigprocmask,发现都不管用 只能自己判断EINTR来重启select了。 在select被EINTR中断时,我输…

移除首页-重回首页

之前发布了一篇文章《订餐系统之获取淘宝外卖订单》,因为是关于淘宝外卖的,所以文中出现这个词时,都加了链接,还设置了 target_blank,就是为了让看的人方便点击,查看。后来,博客园说这个文章中含有推广链接…

sap客户信贷_信贷控制,FD32的销售值不会变化,只有应收总额的变化

请去检查 行项目类型的设定.里面有个栏位 Credit active , 我基本可以确定这里没有勾上才会出现你的问题.ID: Item with active credit function / relevant for creditSpecifies whether the credit management functions (credit checks and update statistics) for order, d…

Scrum之 Sprint计划会议

在sprint第一天召开sprint计划会议,这个会议分为两部分,计划会议1由PO、SM和Team参加,主要是从产品backlog中挑选出需要放到当前sprint下的既定产品backlog,然后由SM、Team参加计划会议2,把既定产品backlog的故事拆分成…

树莓派dht11 python_树莓派使用DHT11温湿度传感器

使用wiringpi编写C程序:如下程序借鉴了网上一老外的程序,忘了原帖地址在哪。#include #include #include #include #define MAX_TIME 85#define DHT11PIN 7#define ATTEMPTS 5 //retry 5 times when no responseint dht11_val[5]{0,0,0,…

java 输出流_Java中输入输出流方法总结

4.如果你创建了一个文件对象,你可以使用下面的方法来获得文件的相关信息,对文件进行操作。1)文件名的操作public String getName();返回文件对象名字符串,串空时返回nullpublic String toString();返回文件名字符串public String getParent()…

Windows 8操作技巧之快捷键大全

Windows 8操作系统发布之后,因为其新颖的界面和对触屏友好的设计,使许多长期使用Windows系统的用户,也觉得一时难以适应,一些操作方式也不知道如何去实现。在Windows系统中,快捷键无疑是提高操作速度的杀手锏。然而&am…

Scrum之 站立例会

在sprint期间,每天都会通过站立例会来进行沟通,以下我将把会议主要内容罗列一下。(以下会议内容来自于Scrum Checklists) 会议内容 目标 团队成员间工作进度的沟通和协调 会议准备 邀请与会者:团队所有成员、Scrum Master、产品负…

Java中带标签的break,continue

首先不带标签的break,continue 就不介绍了。大家平时用的最多的也就是这样的情况了。 首先Java中没有goto&#xff0c;但是可以利用带标签的break, continue来实现类似的跳转。 首先来看一个例子&#xff1a; label:for (int i 0; i < 10; i) {for (int j 0; j < 10; j…

Scrum之 回顾会议

Scrum中Sprint计划会议是最重要的事件&#xff0c;第二重要的事件就是回顾会议&#xff0c;因为这是团队做改进的最佳时机。如果没有回顾&#xff0c;就会发现团队在重犯相同的错误。在sprint的评审会议后&#xff0c;团队需要进行一次回顾会议&#xff0c;以下我将把会议主要内…

java删除换行符号_如何从Java中删除文件中的换行符?

如其他答案所述&#xff0c;您的代码主要String.replace(...)不起作用&#xff0c;因为不会更改目标字符串。(它不能 - Java字符串是不可变的&#xff01;)它实际上做的是创建一个新的String&#xff0c;其中的字符根据需要进行了更改。但是你的代码然后扔掉那个String ...这是…

C#学习之按钮点击事件

描述&#xff1a;asp.net中服务器控件Button的点击事件OnClientClick和OnClick的区别&#xff1f; 解答&#xff1a;http://www.cnblogs.com/ypfnet/archive/2012/12/24/2830771.html&#xff08;作者&#xff1a;代号小子&#xff09; 一、 二者的区别&#xff1a; OnClick是…

Scrum之 评审会议

在sprint周期最后&#xff0c;需要进行一次评审会议&#xff0c;让团队向产品负责人和利益相关者展示已完成的功能。sprint审核的大部分实践用于团队成员展示功能、回答利益相关者对展示的疑问并记录所期望的更改。评审会议可以吸引相关利益者的关注&#xff0c;让其他人了解团…

Bringing up interface eth0: Device eth0 does not seem to be presen

故障现象&#xff1a;51Testing软件测试网.M|{,lbr 51Testing软件测试网l]9H/f[w)h service network restart51Testing软件测试网l^i2t?|5zT8J-s Shutting down loopback insterface: [ OK ]51Testing软…

java的未检查异常有哪些_Java:检查异常与未检查异常

一、异常的介绍Throwable 是 Java 中所有错误和异常的超类。Java 虚拟机仅抛出属于此类(或其子类之一)的实例对象&#xff0c;或者是 throw 语句也可以抛出该对象。同样&#xff0c;catch 子句中的参数类型也只能是此类(或其子类之一)。处于编译时检查异常为目的&#xff0c;Th…

warning:deprecated conversion from string constant to 'char *'解决方案

Linux 环境下当GCC版本比较高时&#xff0c;编译代码可能出现的问题 问题是这样产生的&#xff0c;先看这个函数原型&#xff1a; void someFunc(char *someStr); 再看这个函数调用&#xff1a; someFunc("Im a string!"); 把这两个东西组合起来&#xff0c;用最新的…

利用SVN工具下载OpenCore代码

OpenCore原来使用的是CVS管理代码的。从09年起&#xff0c;更换用SVN管理代码&#xff0c;大家可以用TortoiseSVN软件下载代码&#xff0c;网址是&#xff1a;http://tortoisesvn.net/&#xff0c;安装后tortoiseSVN会和window的资源管理器右键菜单紧密结合在一起&#xff0c;使…

java array_Java 数组

Java 数组数组对于每一门编辑应语言来说都是重要的数据结构之一&#xff0c;当然不同语言对数组的实现及处理也不尽相同。Java语言中提供的数组是用来存储固定大小的同类型元素。你可以声明一个数组变量&#xff0c;如numbers[100]来代替直接声明100个独立变量number0&#xff…

idea 执行 java jar_idea打包java可执行jar包的实现步骤

1,在项目上鼠标右键 --> Open Module Settings2, Artifacts --> --> JAR --> From modules with dependencies...3, Main Class是你这个项目(脚本)的主方法,就是要运行的类,选一个4,如下图,设置 META-INF/MANIFEST.MF!!!!!切记,不能用默认的(起码我用默认的是不成…