はじめに
7 月 11 日〜8 月 27 日、1 ヶ月半が過ぎ去った。週単位で時間が過ぎるのが特に速く感じる。
毎日忙しいが、何に忙しかったか覚えていない。期間中
-
新しい本を全く開いていない(ブログ執筆時に Node や JS を少し開いた程度。内容はかなり忘れてしまった)
-
エッセイを 1.5 編読んだ
-
Kindle を 2 回充電したが、一度も使用していない
-
日本語学習は第 7 課まで終了
-
月曜日は FEX 周刊(一度だけ火曜日に発行されたことも)、金曜日は奇舞周刊(今週は凹凸实验室からの mock 淘宝造物節パノラマが良かった)
最近何の本を読んでますか、おすすめはありますか?
日本語の本、まとまった時間がないので。日常業務に慣れれば時間ができるでしょう
本当にそうか?なぜまとまった時間がないのか?
一。問題の概要
URL 規格の方法で host を取得し、host を判定してください。単一の文字で判定しないでください
シーンはこうだ。現在のページの query string に url パラメータが含まれており、そこから hostname を解析する必要がある
location.hostname で現在のページのホスト名は取得できる。では任意の URL 文字列の場合は?非正規表現方案はあるか?
以前は JS API に new URL() などは提供されていないと思っていた。正規表現で解析するしかないと思っていた
外出して相談した時、三人のベテランが瞬時に 3 つの方案を提示してくれた
二。解決方案
標準 URL 形式:scheme://domain:port/path?query_string#fragment_id。シンプルな正規表現キャプチャで分分钟解析できる
奇妙な(意図的に作られた)URL もある:
http://www.example.com/public/page/2015/index.html?url=http://12.23.34.45/hack.html?http://www.example.com//check.htm
http://www.example.com/public/page/2015/index.html?url=http://www.example.com @12.23.34.45/hack.html
P.S. 分かりやすく���るため、url パラメータ部分は encode していない。こんなパラメータは不穏に見える
規格に合わない URL もあり、一般的な正規表現では対応が難しい。例えば:
// これはどう解釈する?
http://www.example.com/what??key=val?&{http:// @www.abc.com?query=2#45
// これは?
http://www.example.com:8899 @www.abc.com/what??key=val?&{http://?query=2#45
// これは?
http://www.example.com:$88;9,9 @www.abc.com$/what??key=val?&{http://?query=2#45
//...
1.a タグで URL 自動解析
var a = document.createElement('a');
a.href = 'http://www.example.com/news.php?id=10#footer';
var div = document.createElement('div');
for (var key in a) {
!(key in div) && console.log(`${key} = ${a[key]}`);
}
出力結果は以下の通り:
// リソースがどこを指すかを示す。現在のウィンドウ、新しいタブなど
target =
// UA にリソースのダウンロードを通知する
download =
// リンククリック時に指定アドレスへ非同期 POST。広告統計に使用
ping =
// 指すリソースと現在のリソースの関係を示す。代役、ブックマークなど
rel =
// 指すリソースの言語
hreflang =
// 指すリソースの MIME type
type =
// リクエストヘッダー referer 字段の戦略。ユーザープライバシー保護に使用
referrerpolicy =
//
text =
// 廃止済み。カスタム形状をサポート。一連の座標点を渡す
coords =
// 廃止済み。指すリソースの文字コード
charset =
// 廃止済み。指定 name のタグへジャンプ
name =
// 廃止済み。逆関係。rel の反対語
rev =
// 廃止済み。カスタム形状ホットエリアの指定に使用
shape =
// 指すリソースの URL、または URL の#fragment_id 部分
href = http://www.example.com/news.php?id=10#footer
origin = http://www.example.com
protocol = http:
username =
password =
host = www.example.com
hostname = www.example.com
port =
pathname = /news.php
search = ?id=10
hash = #footer
これらは a タグ固有の属性。欲しい hostname も含まれている。つまり、a タグが URL 解析を自動完了する。フロントエンドにとって、これはかつてURL 解析の最も安価な方法だった:
var getHostname = function(url) {
var a = document.createElement('a');
a.href = url;
return a.hostname;
};
100% 信頼できる。どんなに複雑な URL もブラウザを騙せない
2.JS URL API
var url = new URL('http://www.example.com:$88;9,9 @www.abc.com$/what??key=val?&{http://?query=2#45');
for (var key in url) {
console.log(`${key} = ${url[key]}`);
}
Chrome での出力結果:
searchParams = %3Fkey=val%3F
href = http://www.example.com:$88%3B9,9 @www.abc.com%24/what?%3Fkey=val%3F#123http://?query=2#45
origin = http://www.abc.com%24
protocol = http:
username = www.example.com
password = $88%3B9,9
host = www.abc.com%24
hostname = www.abc.com%24
port =
pathname = /what
search = ?%3Fkey=val%3F
hash = #123http://?query=2#45
この URL は規格に合わなさすぎて、UA の処理詳細に差異がある。FF での結果は異なる:
"href = http://www%2Eexample%2Ecom:$88%3B9,9 @www.abc.com$/what??key=val?&{http://?query=2#45"
"origin = http://www.abc.com$"
"protocol = http:"
username = www%2Eexample%2Ecom
password = $88%3B9,9
host = www.abc.com$
hostname = www.abc.com$
port =
pathname = /what
search = ??key=val?&&
searchParams = %3Fkey=val%3F
hash = #123http://?query=2#45
ブラウザはこっそり URL クラスを提供している。ES5 でも ES6、7 規格でもない。現在は実験的な特性。互換性は以下の通り:
Android4.0 webkitURL
Android4.4 URL
Safari6.0 webkitURL
Chrome32 URL
FF19 URL
IE10 URL
モバイルではほぼ安心して使用可能。より多くの互換性情報は URL - Web APIs | MDN を参照
var getHostname = function(url) {
return new URL(url).hostname;
};
3. 正規表現解析
var parseUrl = function(url) {
var urlParseRE = /^\s*(((([^:\/#\?]+:)?(?:(\/\/)((?:(([^: @\/#\?]+)(?:\:([^: @\/#\?]+))?) @)?(([^:\/#\?\]\[]+|\[[^\/\] @#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/;
var matches = urlParseRE.exec(url || "") || [];
return {
href: matches[0] || "",
hrefNoHash: matches[1] || "",
hrefNoSearch: matches[2] || "",
domain: matches[3] || "",
protocol: matches[4] || "",
doubleSlash: matches[5] || "",
authority: matches[6] || "",
username: matches[8] || "",
password: matches[9] || "",
host: matches[10] || "",
hostname: matches[11] || "",
port: matches[12] || "",
pathname: matches[13] || "",
directory: matches[14] || "",
filename: matches[15] || "",
search: matches[16] || "",
hash: matches[17] || ""
};
};
怖くて泣いた。試してみよう。十分堅牢か:
var url = parseUrl('http://www.example.com:$88;9,9 @www.abc.com$/what??key=val?&{http://?query=2#45');
for (var key in url) {
console.log(`${key} = ${url[key]}`);
}
出力結果:
href = http://www.example.com:$88;9,9 @www.abc.com$/what??key=val?&{http://?query=2#45
hrefNoHash = http://www.example.com:$88;9,9 @www.abc.com$/what??key=val?&&
hrefNoSearch = http://www.example.com:$88;9,9 @www.abc.com$/what
domain = http://www.example.com:$88;9,9 @www.abc.com$
protocol = http:
doubleSlash = //
authority = www.example.com:$88;9,9 @www.abc.com$
username = www.example.com
password = $88;9,9
host = www.abc.com$
hostname = www.abc.com$
port =
pathname = /what
directory = /
filename = what
search = ??key=val?&&
hash = #123http://?query=2#45
FF と完全に一致。結果の信頼性は高い。ではこの無敵の正規表現を解釈してみよう:
/^ #href
\s*
( #hrefNoHash
( #hrefNoSearch
( #domain
([^:\/#\?]+:)? #protocol
(?:
(\/\/) #doubleSlash
( #authority
(?:
( #結果取得時に$7 はスキップされる。非キャプチャ型括弧 (?: も使うべき
([^: @\/#\?]+) #username
(?:
\:
([^: @\/#\?]+) #password
)?
)
@
)?
( #host
([^:\/#\?\]\[]+|\[[^\/\] @#?]+\]) #hostname
(?:
\:
([0-9]+) #port
)?
)
)?
)?
)?
( #pathname
(\/?(?:[^\/\?#]+\/+)*) #directory
([^\?#]*) #filename
)
)?
(\?[^#]+)? #search
)
(#.*)? #hash
/
上記分析によると、9 番目の左括弧は非キャプチャ型括弧 (?: を使うべき。値取得時に $7 をスキップしなくて済む。以下の通り:
var getHostname = function(url) {
// 9 番目の小括弧を変更
var urlParseRE = /^\s*(((([^:\/#\?]+:)?(?:(\/\/)((?:(?:([^: @\/#\?]+)(?:\:([^: @\/#\?]+))?) @)?(([^:\/#\?\]\[]+|\[[^\/\] @#?]+\])(?:\:([0-9]+))?))?)?)?((\/?(?:[^\/\?#]+\/+)*)([^\?#]*)))?(\?[^#]+)?)(#.*)?/;
var matches = urlParseRE.exec(url || "") || [];
return matches[10] || "";
};
目が眩んだ。正規表現よさらば。
三。方案分析
a タグ
ベテラン 1 はフロントエンド経験が豊富。冷门技巧で瞬時に問題を解決
互換性に問題なし(何年も前の技巧)。純フロントエンド方案。シンプルで効果的。a タグがこんなに強力とは
より多くの冷门技巧は 前端不为人知的一面--前端冷知识集锦 を参照。昨日新たに発見した別の先輩。追随する
URL クラス
ベテラン 2 は視野が広く、詳細が扎实
非標準の URL クラスも知っている。私は毎日 console を使っているが、これには気づかなかった。注意しないと経験が減る。スーパーマリオのように
無敵の正規表現
ベテラン 3 は問題解決経験が豊富。リソース蓄積が多い
この正規表現、怖くて泣いた。orz
四。まとめ
早出晩帰、経験値上がらず。私は何に忙しかったのか?
時間が細切れ。明確な現在のタスクがない。ふと顔を上げると、また 30 分が過ぎ去った。ふと気づくと、また週例会だ……1 ヶ月半が過ぎ去った。経験値は少しも上がっていない
このままでは、ただのコーダーに堕ちる(3 年の仕事経験、1 年の仕事経験)
コメントはまだありません