這是一個因爲對 JavaScript 函數上下文理解不夠深刻而遇到的坑。html
在表單驗證中,利用高階函數,抽象一個能夠返回特定驗證邏輯的驗證函數:app
// 正則匹配 const getParser = (type) => { switch (type) { case 'chname': return /^([\u4e00-\u9fa5]+|([a-zA-Z]+\s?)+)$/g; case 'email': return /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/; case 'phone': return /^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$/; case 'password': return /^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])[a-zA-Z0-9!@#$%^&*()]{8,16}$/; default: return () => false; } }; const getMatch = (value) => `${value}`.match; const isValid = (value, type) => getMatch(value)(getParser(type)); isValid('12345678901', 'phone');
執行 getMatch(value)(getParser(type))
的時候,沒法完成驗證,程序陷入中止,沒法往下執行。函數
在執行形如 var a = obj.func
的代碼的時候,咱們覺得獲得的變量 a
的上下文是 obj
,而後執行 a()
的時候,就會跟執行 obj.func()
同樣;然而實際上,獲得的 a
只是一個單純的函數,並不會自動綁定 obj
爲上下文。code
再來看上面的代碼的最後一句:htm
const isValid = (value, type) => getMatch(value)(getParser(type));
經過 getMatch(value)
獲得一個 match
方法,可是與預期不一樣,此時獲得的 match
方法的上下文並非 value
,於是會執行失敗。對象
知道了緣由,很明顯解決辦法就是爲要使用的 match
方法綁定上下文。在 Javascript 中,有不少種方法能夠實現:ip
/// bind const getMatch = (value) => `${value}`.match.bind(value); const isValid = (value, type) => getMatch(value)(getParser(type)); /// call const getMatch = (value) => `${value}`.match; const isValid = (value, type) => getMatch(value).call(value, getParser(type)); /// apply const getMatch = (value) => `${value}`.match; const isValid = (value, type) => getMatch(value).apply(value, [getParser(type)]);
JavaScript 的面向對象特性,比想象中還要弱一些。根本沒有什麼 「類方法」 ,全部形如 obj.func1()
的點操做方法執行,只不過是將 obj
做爲上下文去執行 func1
函數罷了。須要特別注意的是,只有在點操做以後立刻執行,纔會有上下文,給人形成是 「調用了對象 obj
裏面的 func1
方法」 的假象;若是如上文描述那樣進行了賦值操做 func2 = obj.func1
,則在執行 func2
的時候就不會有什麼上下文了。get