当我在多个语句中将相同的变量设置为相同的正则表达式值时会发生什么?

时间:2017-09-20 22:33:03

标签: javascript

让我说我这样做:

re = /cat/;
re = /cat/;

从阅读Zakas关于Javascript的书中,似乎在执行第二行时,在内存中没有创建新的RegExp对象。相反,re指向同一个。这是如何工作的“引擎盖下”? Javascript是否以某种方式检查re中已存储的内容?如果我写了怎么办?

re = /cat/;
re = /cats/;

当然,第二行会创建一个新的RegExp对象吗? Javascript如何明确决定编写新对象或保留现有对象?

让我得出结论的书的部分说:

  

在ECMAScript 3中,正则表达式文字总是共享相同的   RegExp实例,始终通过构造函数创建新的RegExp   导致一个新的实例。请考虑以下事项:

var re = null, i;
for (i=0; i < 10; i++){ 
    re = /cat/g;
    re.test(“catastrophe”); 
}
     

在第一个循环中,只创建了一个RegExp实例   / cat /,即使它是在循环体中指定的。例   属性(在下一节中提到)不会重置,所以调用   test()每隔一次都会在循环中失败。这是因为   在第一次调用test()时找到“cat”,但是第二次调用   从索引3(最后一场比赛结束)开始搜索,但不能   找到它。由于找到了字符串的结尾,后续调用   test()从头开始。

通过“第一循环”,他指的是我发布的那个。

2 个答案:

答案 0 :(得分:3)

作者是错误的,或者Javascript自编写以来发生了重大变化,因为现在不是这样。有关此问题的详细解答,请参阅How often does JavaScript recompile regex literals in functions?

我怀疑作者可能将regexp 编译RegExp 对象混淆了。当编译器看到正则表达式文字时,它可以编译一次。然后它生成每次循环运行的代码,以创建一个使用该已编译的正则表达式执行匹配的新对象。但是每个RegExp对象都有自己的状态。

请注意,他说他正在描述EcmaScript 3.这是EcmaScript的一个非常旧版本,最初发布于1999年.Ec​​maScript 5是从2009年开始的(ES4在开发过程中被放弃了),这就是大多数浏览器已经实施了几年,在过去的几年中,ES6的采用正在逐步实施。也许ES3表现得像他描述的那样,但最近的版本没有。

答案 1 :(得分:1)

我不熟悉这本书,但据我所知,这就是它的工作原理。

var语句创建没有类型的新变量,并将它们附加到本地范围。

var re;
var i;

var re,i

null语句生成一个独立存在的null类型对象。

null

在var语句中分配变量只是将其指向该对象,但它不会成为该对象;它们是分享关系的独立事物。

var re=null,i;  

使用正则表达式语句创建一个新的正则表达式对象,我们可能会或可能不会将其分配给变量。

/cat/g  

re=/cat/g

当我重现你的例子时,它只在firefox52中返回true一次,它永远不会返回false,但如果我将测试的返回值分配给另一个变量,并记录它,我会得到十次真实。

var re=null,i; 

for (i=0;i<10;i++){
    re=/cat/g;
    var x=re.test('catastrophe');
    console.log(x)}
//returns true ten times

我认为Zacas正在解释由于他们实现了javascript而在某些浏览器中发现的怪癖。使用正则表达式或任何语句应该每次创建一个新对象,但有很多东西叫做javascript,其中很多都会尽可能频繁地重用对象,偶尔会导致最终修复的奇怪行为。

我希望有帮助