V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
autoxbc

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

  •  
  •   autoxbc · Jul 16, 2017 · 4265 views
    This topic created in 3208 days ago, the information mentioned may be changed or developed.

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

    '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 replies    2017-07-17 16:55:15 +08:00
    Athrob
        1
    Athrob  
       Jul 16, 2017 via iPhone
    知道是正则,转义挺好的。
    autoxbc
        2
    autoxbc  
    OP
       Jul 16, 2017
    @Athrob 转义破坏了字符串的可读性,尤其是长 url 字符串转义后看着难受
    ericls
        3
    ericls  
       Jul 16, 2017   ❤️ 1
    有什么理由不用 `.includes` 的吗?

    `'www.xjd.com'.includes('jd.com')`
    bumz
        4
    bumz  
       Jul 16, 2017
    隐式转换太坑爹
    Athrob
        5
    Athrob  
       Jul 16, 2017
    @autoxbc #2 有道理
    LioMore
        6
    LioMore  
       Jul 16, 2017
    有点好笑
    rogerchen
        7
    rogerchen  
       Jul 16, 2017 via Android   ❤️ 1
    raw string 被楼主吃掉了
    autoxbc
        8
    autoxbc  
    OP
       Jul 16, 2017 via iPhone
    @rogerchen 请详细说一下,没有看懂
    shuirong1997
        9
    shuirong1997  
       Jul 16, 2017
    之前在群里见到有人提出这个坑... 当时还真没想到...
    iyangyuan
        10
    iyangyuan  
       Jul 16, 2017 via iPhone
    这…不看文档,不深究,单纯无脑看方法名,也能感觉到参数不是字符串
    nino
        11
    nino  
       Jul 16, 2017
    从来不知道 match 还能传字符串
    autoxbc
        12
    autoxbc  
    OP
       Jul 16, 2017
    @iyangyuan
    @nino
    这可不是我编的,有人就是传字符串,教程也这么写
    http://www.w3school.com.cn/jsref/jsref_match.asp
    TJT
        13
    TJT  
       Jul 16, 2017
    原来 match 还能传字符串
    TJT
        14
    TJT  
       Jul 16, 2017
    @autoxbc 回 12 楼
    TJT
        15
    TJT  
       Jul 16, 2017
    不小心按了 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
       Jul 16, 2017
    @TJT 是个野路子用法
    CRVV
        17
    CRVV  
       Jul 16, 2017
    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
       Jul 17, 2017
    @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  
       Jul 17, 2017
    @autoxbc w3school.com.cn 这是个盗版教程网站吧!
    445141126
        20
    445141126  
       Jul 17, 2017   ❤️ 1
    string.search 也是
    xiaojunjor
        21
    xiaojunjor  
       Jul 17, 2017
    会隐式转为正则,就代表可以传字符串,报错才叫做不能传字符串
    marcong95
        22
    marcong95  
       Jul 17, 2017
    @autoxbc “ match 是什么是由 match 的行为决定的”这显然不太合理,match 一词取得是匹配之意,匹配字符串是什么概念?一般的理解都是 match a pattern 吧。所以 match 作为 find 何来符合语义一说? func && func()也只是可读性比较差,其实并没有不符合 JS 的 specs ……

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

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

    @marcong95 我的意思是给 match 传正则参数,得到的匹配结果隐式转换为布尔值,是符合语义的。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   3478 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 163ms · UTC 11:36 · PVG 19:36 · LAX 04:36 · JFK 07:36
    ♥ Do have faith in what you're doing.