在 MDN 上有写明
如果正则表达式设置了全局标志,test() 的执行会改变正则表达式 lastIndex属性。连续的执行test()方法,后续的执行将会从 lastIndex 处开始匹配字符串,(exec() 同样改变正则本身的 lastIndex属性值).
var s1 = "foo"; var s2 = "foo"; var regex = /foo/g; // regex.lastIndex is at 0 regex.test(s1); // true // regex.lastIndex is now at 3 regex.test(s2); // false 由此可见,导致正则连续匹配出错的原因是全局匹配下生效的lastIndex属性。 二、lastIndex 在讨论之前,先简单回顾一下 JS中正则表达式的使用方式 JS 中正则表达式的使用方式有两种: 第一种是正则表达式对象的方法,常用方法有两个。 exec(str) : 检索字符串中指定的值。返回找到的值,并确定其位置test(str) : 检索字符串中指定的值。返回 true 或 false 第二种是字符串对象的方法,常用方法有四个。 match(regexp) : 找到一个或多个正则表达式的匹配(该数组的内容依赖于 regexp 是否具有全局标志 g)replace(regexp, replacement) : 替换与正则表达式匹配的子串 (replacement可以是字符串或函数、lambda表达式)search(regexp) : 检索与正则表达式相匹配的值,返回首次匹配项的索引split(search) : 把字符串分割为字符串数组 字符串的全局匹配其实就是依赖方法 RegExp.exec( ) 和 RegExp.test( ) ,它们都以 lastIndex 属性所指的位置作为下次检索的起始点。 这样,就可以通过反复调用这两个方法来遍历一个字符串中的所有匹配文本。 需要注意的是,该属性只有设置标志 g才能使用。 三、解决方案 第一种方案 如上面所述,我们 lastIndex 属性必须要设置 g 标签才能使用。 那么我们在匹配的时候,可以根据情况,直接去掉 g 标签就可以啦。 var s1 = "foo"; var s2 = "foo"; var regex = /foo/; regex.test(s1); // true regex.test(s2); // true 第二种方案 很多时候,我们必须要执行 全局匹配( g ),这时候就不能使用第一种方案了。 那么我们可以手动将 lastIndex 重置为 0。 这样,我们再次执行全局匹配的时候,就不会出现 false 的情况了。 var s1 = "foo"; var s2 = "foo"; var regex = /foo/g; regex.test(s1); // true regex.lastIndex = 0 regex.test(s2); // true 第三种方案 使用字符串对象的正则匹配方法 var s1 = "foo"; var s2 = "foo"; var s3 = "abb"; var regex = /foo/g; s1.match(regex) // ['foo'] s2.match(regex) // ['foo'] s3.match(regex) // null s1.search(regex) // 0 s2.search(regex) // 0 s3.search(regex) // -1 参考链接: 为什么使用正则RegExp.test( )方法时第一次是 true,第二次是false? 1、在java中使用import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTest { public static void main(String[] args) { String xx = "^(?:(?!0000)[0-9]{4}([-/. var reg = /^[a-z][a-z0-9_]*$/g; console.log(reg.test('sadf6')) console.log(reg.test('sadf6')) 打印结果一次是true,一次是false 这是因为正则reg的g属性,设置的全局匹配。RegExp有一个lastIndex属性,来保存索引开始位置,也就是说第二次正则会在索引为5的地方验证,那么这个时... 从一堆手机号码中,找出xyz可不连续且重复4次的手机号码package test;import java.util.regex.Matcher; import java.util.regex.Pattern;public class Main { public static Pattern pattern=Pattern.compile("(\\d{3})(.*\\1){2}"); pu 则表达式:在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“re... 当第一次使用test()时,lastIndex为当前字符串最后一个字符的索引。第二次使用test()时,lastIndex由上次的索引值继续向下,所以为false。输入的第一个端口为true,第二个端口后为false,即当分隔到的数组长度大于1时返回的数据为false,导致验证无法通过。在解决多端口的单项验证时,需要将以逗号分隔的端口切割为数组。3 - 对单端口进行端口规则验证:必须为0-65535之间的纯数字。1 - 对用户输入的多端口数据进行分割,分割为数组。的使用,直接使用正则去匹配。 正则就是一种规则的的表达式,书写一段规则,用于匹配一段字符串是否符合规则创建正则表达式创建正则表达式有两种方式:1.字面量的形式2.内置构造函数的形式 * 1. 字面量的形式 const reg = / abc / * 2. 内置构造函数的形式 const reg1 = new RegExp('abc') console . log(reg) // /abc/ console . log(reg1) // /abc/ *1. 首先,看下面的代码,我以为它三次调用find()方法都会返回true,但实际上并不是。 public class Demo { public static void main(String[] args) { String str = "hello 123!"; String regex = "(\\d+)"; Matcher matcher = Pattern.compile(regex).matcher(str); System.o
由此可见,导致正则连续匹配出错的原因是全局匹配下生效的lastIndex属性。
在讨论之前,先简单回顾一下 JS中正则表达式的使用方式
JS 中正则表达式的使用方式有两种:
第一种是正则表达式对象的方法,常用方法有两个。
第二种是字符串对象的方法,常用方法有四个。
字符串的全局匹配其实就是依赖方法 RegExp.exec( ) 和 RegExp.test( ) ,它们都以 lastIndex 属性所指的位置作为下次检索的起始点。 这样,就可以通过反复调用这两个方法来遍历一个字符串中的所有匹配文本。
需要注意的是,该属性只有设置标志 g才能使用。
如上面所述,我们 lastIndex 属性必须要设置 g 标签才能使用。 那么我们在匹配的时候,可以根据情况,直接去掉 g 标签就可以啦。
var s1 = "foo"; var s2 = "foo"; var regex = /foo/; regex.test(s1); // true regex.test(s2); // true 第二种方案 很多时候,我们必须要执行 全局匹配( g ),这时候就不能使用第一种方案了。 那么我们可以手动将 lastIndex 重置为 0。 这样,我们再次执行全局匹配的时候,就不会出现 false 的情况了。 var s1 = "foo"; var s2 = "foo"; var regex = /foo/g; regex.test(s1); // true regex.lastIndex = 0 regex.test(s2); // true 第三种方案 使用字符串对象的正则匹配方法 var s1 = "foo"; var s2 = "foo"; var s3 = "abb"; var regex = /foo/g; s1.match(regex) // ['foo'] s2.match(regex) // ['foo'] s3.match(regex) // null s1.search(regex) // 0 s2.search(regex) // 0 s3.search(regex) // -1 参考链接: 为什么使用正则RegExp.test( )方法时第一次是 true,第二次是false? 1、在java中使用import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTest { public static void main(String[] args) { String xx = "^(?:(?!0000)[0-9]{4}([-/. var reg = /^[a-z][a-z0-9_]*$/g; console.log(reg.test('sadf6')) console.log(reg.test('sadf6')) 打印结果一次是true,一次是false 这是因为正则reg的g属性,设置的全局匹配。RegExp有一个lastIndex属性,来保存索引开始位置,也就是说第二次正则会在索引为5的地方验证,那么这个时... 从一堆手机号码中,找出xyz可不连续且重复4次的手机号码package test;import java.util.regex.Matcher; import java.util.regex.Pattern;public class Main { public static Pattern pattern=Pattern.compile("(\\d{3})(.*\\1){2}"); pu 则表达式:在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“re... 当第一次使用test()时,lastIndex为当前字符串最后一个字符的索引。第二次使用test()时,lastIndex由上次的索引值继续向下,所以为false。输入的第一个端口为true,第二个端口后为false,即当分隔到的数组长度大于1时返回的数据为false,导致验证无法通过。在解决多端口的单项验证时,需要将以逗号分隔的端口切割为数组。3 - 对单端口进行端口规则验证:必须为0-65535之间的纯数字。1 - 对用户输入的多端口数据进行分割,分割为数组。的使用,直接使用正则去匹配。 正则就是一种规则的的表达式,书写一段规则,用于匹配一段字符串是否符合规则创建正则表达式创建正则表达式有两种方式:1.字面量的形式2.内置构造函数的形式 * 1. 字面量的形式 const reg = / abc / * 2. 内置构造函数的形式 const reg1 = new RegExp('abc') console . log(reg) // /abc/ console . log(reg1) // /abc/ *1. 首先,看下面的代码,我以为它三次调用find()方法都会返回true,但实际上并不是。 public class Demo { public static void main(String[] args) { String str = "hello 123!"; String regex = "(\\d+)"; Matcher matcher = Pattern.compile(regex).matcher(str); System.o
var s1 = "foo"; var s2 = "foo"; var regex = /foo/; regex.test(s1); // true regex.test(s2); // true
第二种方案 很多时候,我们必须要执行 全局匹配( g ),这时候就不能使用第一种方案了。 那么我们可以手动将 lastIndex 重置为 0。 这样,我们再次执行全局匹配的时候,就不会出现 false 的情况了。 var s1 = "foo"; var s2 = "foo"; var regex = /foo/g; regex.test(s1); // true regex.lastIndex = 0 regex.test(s2); // true 第三种方案 使用字符串对象的正则匹配方法 var s1 = "foo"; var s2 = "foo"; var s3 = "abb"; var regex = /foo/g; s1.match(regex) // ['foo'] s2.match(regex) // ['foo'] s3.match(regex) // null s1.search(regex) // 0 s2.search(regex) // 0 s3.search(regex) // -1 参考链接: 为什么使用正则RegExp.test( )方法时第一次是 true,第二次是false? 1、在java中使用import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTest { public static void main(String[] args) { String xx = "^(?:(?!0000)[0-9]{4}([-/. var reg = /^[a-z][a-z0-9_]*$/g; console.log(reg.test('sadf6')) console.log(reg.test('sadf6')) 打印结果一次是true,一次是false 这是因为正则reg的g属性,设置的全局匹配。RegExp有一个lastIndex属性,来保存索引开始位置,也就是说第二次正则会在索引为5的地方验证,那么这个时... 从一堆手机号码中,找出xyz可不连续且重复4次的手机号码package test;import java.util.regex.Matcher; import java.util.regex.Pattern;public class Main { public static Pattern pattern=Pattern.compile("(\\d{3})(.*\\1){2}"); pu 则表达式:在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“re... 当第一次使用test()时,lastIndex为当前字符串最后一个字符的索引。第二次使用test()时,lastIndex由上次的索引值继续向下,所以为false。输入的第一个端口为true,第二个端口后为false,即当分隔到的数组长度大于1时返回的数据为false,导致验证无法通过。在解决多端口的单项验证时,需要将以逗号分隔的端口切割为数组。3 - 对单端口进行端口规则验证:必须为0-65535之间的纯数字。1 - 对用户输入的多端口数据进行分割,分割为数组。的使用,直接使用正则去匹配。 正则就是一种规则的的表达式,书写一段规则,用于匹配一段字符串是否符合规则创建正则表达式创建正则表达式有两种方式:1.字面量的形式2.内置构造函数的形式 * 1. 字面量的形式 const reg = / abc / * 2. 内置构造函数的形式 const reg1 = new RegExp('abc') console . log(reg) // /abc/ console . log(reg1) // /abc/ *1. 首先,看下面的代码,我以为它三次调用find()方法都会返回true,但实际上并不是。 public class Demo { public static void main(String[] args) { String str = "hello 123!"; String regex = "(\\d+)"; Matcher matcher = Pattern.compile(regex).matcher(str); System.o
很多时候,我们必须要执行 全局匹配( g ),这时候就不能使用第一种方案了。 那么我们可以手动将 lastIndex 重置为 0。 这样,我们再次执行全局匹配的时候,就不会出现 false 的情况了。
var s1 = "foo"; var s2 = "foo"; var regex = /foo/g; regex.test(s1); // true regex.lastIndex = 0 regex.test(s2); // true 第三种方案 使用字符串对象的正则匹配方法 var s1 = "foo"; var s2 = "foo"; var s3 = "abb"; var regex = /foo/g; s1.match(regex) // ['foo'] s2.match(regex) // ['foo'] s3.match(regex) // null s1.search(regex) // 0 s2.search(regex) // 0 s3.search(regex) // -1 参考链接: 为什么使用正则RegExp.test( )方法时第一次是 true,第二次是false? 1、在java中使用import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTest { public static void main(String[] args) { String xx = "^(?:(?!0000)[0-9]{4}([-/. var reg = /^[a-z][a-z0-9_]*$/g; console.log(reg.test('sadf6')) console.log(reg.test('sadf6')) 打印结果一次是true,一次是false 这是因为正则reg的g属性,设置的全局匹配。RegExp有一个lastIndex属性,来保存索引开始位置,也就是说第二次正则会在索引为5的地方验证,那么这个时... 从一堆手机号码中,找出xyz可不连续且重复4次的手机号码package test;import java.util.regex.Matcher; import java.util.regex.Pattern;public class Main { public static Pattern pattern=Pattern.compile("(\\d{3})(.*\\1){2}"); pu 则表达式:在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“re... 当第一次使用test()时,lastIndex为当前字符串最后一个字符的索引。第二次使用test()时,lastIndex由上次的索引值继续向下,所以为false。输入的第一个端口为true,第二个端口后为false,即当分隔到的数组长度大于1时返回的数据为false,导致验证无法通过。在解决多端口的单项验证时,需要将以逗号分隔的端口切割为数组。3 - 对单端口进行端口规则验证:必须为0-65535之间的纯数字。1 - 对用户输入的多端口数据进行分割,分割为数组。的使用,直接使用正则去匹配。 正则就是一种规则的的表达式,书写一段规则,用于匹配一段字符串是否符合规则创建正则表达式创建正则表达式有两种方式:1.字面量的形式2.内置构造函数的形式 * 1. 字面量的形式 const reg = / abc / * 2. 内置构造函数的形式 const reg1 = new RegExp('abc') console . log(reg) // /abc/ console . log(reg1) // /abc/ *1. 首先,看下面的代码,我以为它三次调用find()方法都会返回true,但实际上并不是。 public class Demo { public static void main(String[] args) { String str = "hello 123!"; String regex = "(\\d+)"; Matcher matcher = Pattern.compile(regex).matcher(str); System.o
var s1 = "foo"; var s2 = "foo"; var regex = /foo/g; regex.test(s1); // true regex.lastIndex = 0 regex.test(s2); // true
第三种方案 使用字符串对象的正则匹配方法 var s1 = "foo"; var s2 = "foo"; var s3 = "abb"; var regex = /foo/g; s1.match(regex) // ['foo'] s2.match(regex) // ['foo'] s3.match(regex) // null s1.search(regex) // 0 s2.search(regex) // 0 s3.search(regex) // -1 参考链接: 为什么使用正则RegExp.test( )方法时第一次是 true,第二次是false? 1、在java中使用import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTest { public static void main(String[] args) { String xx = "^(?:(?!0000)[0-9]{4}([-/. var reg = /^[a-z][a-z0-9_]*$/g; console.log(reg.test('sadf6')) console.log(reg.test('sadf6')) 打印结果一次是true,一次是false 这是因为正则reg的g属性,设置的全局匹配。RegExp有一个lastIndex属性,来保存索引开始位置,也就是说第二次正则会在索引为5的地方验证,那么这个时... 从一堆手机号码中,找出xyz可不连续且重复4次的手机号码package test;import java.util.regex.Matcher; import java.util.regex.Pattern;public class Main { public static Pattern pattern=Pattern.compile("(\\d{3})(.*\\1){2}"); pu 则表达式:在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“re... 当第一次使用test()时,lastIndex为当前字符串最后一个字符的索引。第二次使用test()时,lastIndex由上次的索引值继续向下,所以为false。输入的第一个端口为true,第二个端口后为false,即当分隔到的数组长度大于1时返回的数据为false,导致验证无法通过。在解决多端口的单项验证时,需要将以逗号分隔的端口切割为数组。3 - 对单端口进行端口规则验证:必须为0-65535之间的纯数字。1 - 对用户输入的多端口数据进行分割,分割为数组。的使用,直接使用正则去匹配。 正则就是一种规则的的表达式,书写一段规则,用于匹配一段字符串是否符合规则创建正则表达式创建正则表达式有两种方式:1.字面量的形式2.内置构造函数的形式 * 1. 字面量的形式 const reg = / abc / * 2. 内置构造函数的形式 const reg1 = new RegExp('abc') console . log(reg) // /abc/ console . log(reg1) // /abc/ *1. 首先,看下面的代码,我以为它三次调用find()方法都会返回true,但实际上并不是。 public class Demo { public static void main(String[] args) { String str = "hello 123!"; String regex = "(\\d+)"; Matcher matcher = Pattern.compile(regex).matcher(str); System.o
使用字符串对象的正则匹配方法
var s1 = "foo"; var s2 = "foo"; var s3 = "abb"; var regex = /foo/g; s1.match(regex) // ['foo'] s2.match(regex) // ['foo'] s3.match(regex) // null s1.search(regex) // 0 s2.search(regex) // 0 s3.search(regex) // -1 参考链接: 为什么使用正则RegExp.test( )方法时第一次是 true,第二次是false? 1、在java中使用import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTest { public static void main(String[] args) { String xx = "^(?:(?!0000)[0-9]{4}([-/. var reg = /^[a-z][a-z0-9_]*$/g; console.log(reg.test('sadf6')) console.log(reg.test('sadf6')) 打印结果一次是true,一次是false 这是因为正则reg的g属性,设置的全局匹配。RegExp有一个lastIndex属性,来保存索引开始位置,也就是说第二次正则会在索引为5的地方验证,那么这个时... 从一堆手机号码中,找出xyz可不连续且重复4次的手机号码package test;import java.util.regex.Matcher; import java.util.regex.Pattern;public class Main { public static Pattern pattern=Pattern.compile("(\\d{3})(.*\\1){2}"); pu 则表达式:在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“re... 当第一次使用test()时,lastIndex为当前字符串最后一个字符的索引。第二次使用test()时,lastIndex由上次的索引值继续向下,所以为false。输入的第一个端口为true,第二个端口后为false,即当分隔到的数组长度大于1时返回的数据为false,导致验证无法通过。在解决多端口的单项验证时,需要将以逗号分隔的端口切割为数组。3 - 对单端口进行端口规则验证:必须为0-65535之间的纯数字。1 - 对用户输入的多端口数据进行分割,分割为数组。的使用,直接使用正则去匹配。 正则就是一种规则的的表达式,书写一段规则,用于匹配一段字符串是否符合规则创建正则表达式创建正则表达式有两种方式:1.字面量的形式2.内置构造函数的形式 * 1. 字面量的形式 const reg = / abc / * 2. 内置构造函数的形式 const reg1 = new RegExp('abc') console . log(reg) // /abc/ console . log(reg1) // /abc/ *1. 首先,看下面的代码,我以为它三次调用find()方法都会返回true,但实际上并不是。 public class Demo { public static void main(String[] args) { String str = "hello 123!"; String regex = "(\\d+)"; Matcher matcher = Pattern.compile(regex).matcher(str); System.o
var s1 = "foo"; var s2 = "foo"; var s3 = "abb"; var regex = /foo/g; s1.match(regex) // ['foo'] s2.match(regex) // ['foo'] s3.match(regex) // null s1.search(regex) // 0 s2.search(regex) // 0 s3.search(regex) // -1
参考链接: 为什么使用正则RegExp.test( )方法时第一次是 true,第二次是false? 1、在java中使用import java.util.regex.Matcher; import java.util.regex.Pattern; public class RegexTest { public static void main(String[] args) { String xx = "^(?:(?!0000)[0-9]{4}([-/. var reg = /^[a-z][a-z0-9_]*$/g; console.log(reg.test('sadf6')) console.log(reg.test('sadf6')) 打印结果一次是true,一次是false 这是因为正则reg的g属性,设置的全局匹配。RegExp有一个lastIndex属性,来保存索引开始位置,也就是说第二次正则会在索引为5的地方验证,那么这个时... 从一堆手机号码中,找出xyz可不连续且重复4次的手机号码package test;import java.util.regex.Matcher; import java.util.regex.Pattern;public class Main { public static Pattern pattern=Pattern.compile("(\\d{3})(.*\\1){2}"); pu 则表达式:在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串。在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容。许多程序设计语言都支持利用正则表达式进行字符串操作。例如,在Perl中就内建了一个功能强大的正则表达式引擎。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。正则表达式通常缩写成“re... 当第一次使用test()时,lastIndex为当前字符串最后一个字符的索引。第二次使用test()时,lastIndex由上次的索引值继续向下,所以为false。输入的第一个端口为true,第二个端口后为false,即当分隔到的数组长度大于1时返回的数据为false,导致验证无法通过。在解决多端口的单项验证时,需要将以逗号分隔的端口切割为数组。3 - 对单端口进行端口规则验证:必须为0-65535之间的纯数字。1 - 对用户输入的多端口数据进行分割,分割为数组。的使用,直接使用正则去匹配。 正则就是一种规则的的表达式,书写一段规则,用于匹配一段字符串是否符合规则创建正则表达式创建正则表达式有两种方式:1.字面量的形式2.内置构造函数的形式 * 1. 字面量的形式 const reg = / abc / * 2. 内置构造函数的形式 const reg1 = new RegExp('abc') console . log(reg) // /abc/ console . log(reg1) // /abc/ *1. 首先,看下面的代码,我以为它三次调用find()方法都会返回true,但实际上并不是。 public class Demo { public static void main(String[] args) { String str = "hello 123!"; String regex = "(\\d+)"; Matcher matcher = Pattern.compile(regex).matcher(str); System.o
参考链接: 为什么使用正则RegExp.test( )方法时第一次是 true,第二次是false?