V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
autoxbc
V2EX  ›  JavaScript

有多少人知道 match 的参数不能是字符串

  •  
  •   autoxbc · 2017-07-16 02:58:48 +08:00 · 3481 次点击
    这是一个创建于 2448 天前的主题,其中的信息可能已经有所发展或是发生改变。

    很多人会这么写字符串匹配,结果似乎也对

    'abcde'.match('cd')
    // Array ["cd"]
    

    实际这是错的,或者说某些情况是错的,来个例子

    // 匹配京东全站
    if( location.hostname.match('.jd.com') )
    // 反例
    'www.xjd.com'.match('.jd.com')
    // Array ["xjd.com"]
    

    道理很简单,match 的参数必须是正则,如果不是,会被隐式转换为正则。

    因为是隐式转换,写的人可能没注意到,转换的结果可能和预期的不一致。

    这里 dot 应该是纯字符串的一部分,被转换成了通配符。

    new RegExp('.jd.com')
    ->   /.jd.com/ 
    

    坑的是匹配结果放宽而不是收窄,所以调试不会出错,但是边界不对了。


    应对方法是用 indexOf

    'www.xjd.com'.indexOf('.jd.com') !== -1
    // false
    

    但是写起来有点长,多出 7 个字符(算上空格),我一般这么写

    !!( 'www.xjd.com'.indexOf('.jd.com')+1 )
    // false
    

    因为基本都是写在 if 语句里的,所以不用显示转换

    if( location.hostname.indexOf('.jd.com')+1 )
    

    当然也可以用 match 加手动转义,但是太丑了

    'www.xjd.com'.match('\\.jd\\.com')
    // null
    'www.xjd.com'.match(/\.jd\.com/)
    // null
    

    大家有什么好的方法说一下

    23 条回复    2017-07-17 16:55:15 +08:00
    Athrob
        1
    Athrob  
       2017-07-16 04:58:19 +08:00 via iPhone
    知道是正则,转义挺好的。
    autoxbc
        2
    autoxbc  
    OP
       2017-07-16 05:10:41 +08:00
    @Athrob 转义破坏了字符串的可读性,尤其是长 url 字符串转义后看着难受
    ericls
        3
    ericls  
       2017-07-16 05:11:15 +08:00   ❤️ 1
    有什么理由不用 `.includes` 的吗?

    `'www.xjd.com'.includes('jd.com')`
    bumz
        4
    bumz  
       2017-07-16 05:13:02 +08:00
    隐式转换太坑爹
    Athrob
        5
    Athrob  
       2017-07-16 05:17:18 +08:00
    @autoxbc #2 有道理
    LioMore
        6
    LioMore  
       2017-07-16 05:58:59 +08:00
    有点好笑
    rogerchen
        7
    rogerchen  
       2017-07-16 11:25:18 +08:00 via Android   ❤️ 1
    raw string 被楼主吃掉了
    autoxbc
        8
    autoxbc  
    OP
       2017-07-16 15:34:03 +08:00 via iPhone
    @rogerchen 请详细说一下,没有看懂
    shuirong1997
        9
    shuirong1997  
       2017-07-16 17:43:54 +08:00
    之前在群里见到有人提出这个坑... 当时还真没想到...
    iyangyuan
        10
    iyangyuan  
       2017-07-16 18:10:19 +08:00 via iPhone
    这…不看文档,不深究,单纯无脑看方法名,也能感觉到参数不是字符串
    nino
        11
    nino  
       2017-07-16 18:24:36 +08:00
    从来不知道 match 还能传字符串
    autoxbc
        12
    autoxbc  
    OP
       2017-07-16 20:30:43 +08:00
    @iyangyuan
    @nino
    这可不是我编的,有人就是传字符串,教程也这么写
    http://www.w3school.com.cn/jsref/jsref_match.asp
    TJT
        13
    TJT  
       2017-07-16 20:32:46 +08:00
    原来 match 还能传字符串
    TJT
        14
    TJT  
       2017-07-16 20:33:48 +08:00
    @autoxbc 回 12 楼
    TJT
        15
    TJT  
       2017-07-16 20:36:36 +08:00
    不小心按了 cmd + enter,
    https://www.w3schools.com/jsref/jsref_match.asp
    https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/match

    都没有说可以传字符串的,MDN 的会说明有隐式转换。
    autoxbc
        16
    autoxbc  
    OP
       2017-07-16 20:46:18 +08:00
    @TJT 是个野路子用法
    CRVV
        17
    CRVV  
       2017-07-16 23:02:21 +08:00
    1. match 的参数可以是字符串,字符串会被转成正则表达式然后匹配。用字符串表示正则表达式是很常见的用法,很多语言不像 JavaScript 一样有专门的正则表达式类型。这个帖子的标题就是错的
    2. match 在几乎所有语言里都是正则表达式匹配,不是子串搜索,我真不知道你们是怎么能造出来把 match 当 find 的用法
    3. w3schools 是著名的垃圾网站,不知道你们为什么不看正经的文档,还是中文的。
    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/match
    autoxbc
        18
    autoxbc  
    OP
       2017-07-17 00:07:26 +08:00
    @CRVV 您太激动了,观点有点偏颇

    1. js 里有些方法就是支持多种类型参数的,比如 replace。对于不支持多类型参数的方法,强行使用非标准输入,并期望(或者根本不知道)隐式转换与预想的一致,这就造成混淆,很容易暗藏 bug,并提高维护成本。您是否认为可以随意使用 js 的灵活性,并在工业环境使用一些魔法代码?

    2. match 是什么是由 match 的行为决定的,不是某些人认为的。当正确使用,match 就是可以充当 find 的角色,这甚至不能算作使用副作用。起码比 func && func() 这种要规范多了。要注意的是,includes 也是 ES6 才出现的,之前基本都是用 indexOf(str) !== -1。match 作为 find,不仅简单而且符合语义。

    3. 我举了 w3schools 的例子,是为说明误用的普遍性,不是否定 w3schools 的价值,也不同意您否定其价值的观点。如果可以随意甩鄙视链,是否可以说 W3C 的文档更正经? MDN 的逼格就不够了? ECMA 也有更详实的文档,这些都是多层次教程的一部分,没有谁是垃圾。
    araraloren
        19
    araraloren  
       2017-07-17 09:32:56 +08:00
    @autoxbc w3school.com.cn 这是个盗版教程网站吧!
    445141126
        20
    445141126  
       2017-07-17 12:57:29 +08:00   ❤️ 1
    string.search 也是
    xiaojunjor
        21
    xiaojunjor  
       2017-07-17 13:28:35 +08:00
    会隐式转为正则,就代表可以传字符串,报错才叫做不能传字符串
    marcong95
        22
    marcong95  
       2017-07-17 16:18:15 +08:00
    @autoxbc “ match 是什么是由 match 的行为决定的”这显然不太合理,match 一词取得是匹配之意,匹配字符串是什么概念?一般的理解都是 match a pattern 吧。所以 match 作为 find 何来符合语义一说? func && func()也只是可读性比较差,其实并没有不符合 JS 的 specs ……

    关于鄙视链的问题,我觉得中文英文才是槽点,w3school 的确是各种错误,鄙视之并无不可。。
    autoxbc
        23
    autoxbc  
    OP
       2017-07-17 16:55:15 +08:00 via iPhone
    @araraloren 我无意给谁做辩护,有错误可以改,不要说人家是垃圾。第三方也没有能力判断是否有授权,不应该下断言。

    @xiaojunjor 除了解释器报错,还应该有编码规范。作为动态语言用户,我接受隐式转换,除非会引发二义性。

    @marcong95 我的意思是给 match 传正则参数,得到的匹配结果隐式转换为布尔值,是符合语义的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5389 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 33ms · UTC 06:59 · PVG 14:59 · LAX 23:59 · JFK 02:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.