有多少人知道 match 的参数不能是字符串 - V2EX
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 4108 次点击
    这是一个创建于 3088 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    '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     Solana     3262 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 04:57 PVG 12:57 LAX 20:57 JFK 23:57
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86