今天同學發了一份騰訊2013校園招聘軟件開發類的筆試題(╮(╯▽╰)╭可惜是拍的圖片)來給我做,我一看到就崩潰了,大部分都不會做,考查的計算機基礎知識主要有C語言、算法和數據結構、計算機操作系統、計算機網絡、數據庫,個別一兩題涉及到編譯原理,分數布局是不定項選擇題60分(20題)、填空題40分(7小題,10空,每空4分)、附加題(分為web前端方法和其他方向),其中web前端方法附加題有一道是這樣的:編寫一個javascript函數,把URL解析為一個結構與頁面中的javascript location的對象相似的對象實體。
如:輸入url串為 "http://www.qq.com/index.html?key1=1&key2=2&key3=3";
最后輸出的對象是:
{ "protocol": "http", "hostname": "www.qq.com", "pathname": "/index.html", "query": "?key1=1&key2=2&key3=3" }
注:如果熟悉url規范,對於更復雜的url,可以嘗試讓解析輸出的對象有更多便於使用的屬性字段。
當看到題目,腦海里就立刻出現了該題大概是考查js對字符串、數組的一些操作的畫面,對於location對象的一些屬性,我想接觸過js的人都比較熟悉,何況像我這種菜鳥,不清楚的去度娘、google搜搜都會出現一大把介紹,這里就不介紹了。題目要求是模擬location對象的實體對象只需擁有四個屬性protocol、hostname、pathname、query即可,但我在實現時增加了一些屬性:如port、hash、查詢字符串對象來增加該實體對象的健壯性(題目注明部分的實現),由於對正則表達式不太熟悉,所以只少量使用了正則(據說正則有時效率挺高的),並且性能方面也沒有進行優化,如果有更好的方案,歡迎大神們給出建議,廢話不多說,下面是我的實現思路,貼上代碼:
// 對形如http://www.qq.com:80/index.html?key1=1&key2=2&key3=3#hcy的url字符串進行解析,並返回類似location對象的實體對象 var parseUrl = function() { var pos1, // 保存":"字符的位置(注意是前半部分字符串里的":") pos2, // 保存"/"字符的位置 pos3, // 保存"?"字符的位置 pos4, // 保存"#"字符的位置 pos5, // 保存":"字符的位置(注意是后半部分字符串里的":") protocol, // 協議 hostname, // 主機名 port, // 端口 pathname, // 路徑 queryStr, // 查詢字符串 hash, // 錨標記信息 matchArr, beforeStr, // 前半部分字符串 afterStr, // 后半部分字符串 queryObj = {}, // 保存查詢字符串基於名值對(key=value)的數據對象 url = arguments[0]; // 獲取url字符串 matchArr = url ? url.split("//") : alert("請輸入url"); // 根據"//"分隔符把字符串分隔成數組的兩項 beforeStr = matchArr[0]; afterStr = matchArr[1]; // 獲取相應字符位置,注意:當查找的字符串不存在時返回-1 pos1 = beforeStr.indexOf(":"); pos2 = afterStr.indexOf("/"); pos3 = afterStr.indexOf("?"); pos4 = afterStr.indexOf("#"); pos5 = afterStr.indexOf(":"); // 獲取協議 protocol = pos1 > -1 ? beforeStr.slice(0, pos1) : ""; // 獲取主機名 hostname = pos5 > -1 ? afterStr.slice(0, pos5) : afterStr.slice(0); // 獲取端口,默認為80(輸出空字符串),其他正常輸出 port = pos5 > -1 ? pos2 > -1 ? afterStr.slice(pos5 + 1, pos2) : afterStr.slice(pos5 + 1) : ""; port = parseInt(port) === 80 ? "" : port; // 獲取路徑,注意對空值進行處理 pathname = pos3 > -1 && (pos2 > -1) ? afterStr.slice(pos2, pos3) : pos2 > -1 ? afterStr.slice(pos2) : ""; // 獲取查詢字符串,注意對空值進行處理 queryStr = pos4 > -1 ? (pos3 > -1) && afterStr.slice(pos3, pos4) : pos3 > -1 ? afterStr.slice(pos3) : ""; hash = pos4 > -1 ? afterStr.slice(pos4) : ""; // 獲取錨(存在時直接返回,不存在時返回空字符串) // 對queryString進行處理 var arr = queryStr ? queryStr.replace(/\?*/,"").split("&") : [], item, name, value; for (var i = 0; i < arr.length; i++) { item = arr[i].split("="); name = item[0], // 獲取名值對的名稱 value = item[1]; // 獲取名值對的值 // 把每一"名值對"構造成數據對象 queryObj[name] = value; } // 返回一個包含上述屬性的對象 return { protocol: protocol, hostname: hostname, port: port, pathname: pathname, queryStr: queryStr, hash: hash, queryObj: queryObj }; };
測試代碼:
// 測試 var url1 = "http://", url2 = "http://www.qq.com", url3 = "http://www.qq.com:80", url4 = "http://www.qq.com:81", url5 = "http://www.qq.com:81/index.html", url6 = "http://www.qq.com:81/index.html?key1=1&key2=2&key3=3", url7 = "http://www.qq.com:81/index.html?key1=1&key2=2&key3=3#hcy"; var entityObj = parseUrl(url7); // 獲取返回的對象 for (var k in entityObj) { // 對查詢字符串對象進行處理 if (typeof entityObj[k] === "object") { for (var name in entityObj[k]) { console.log(name + ":\t" + entityObj[k][name]); } } else if (entityObj.hasOwnProperty(k) || typeof k !== "function") { console.log(k + ":\t" + entityObj[k]); } }
測試結果:
1、對於url1字符串:
2、對於url2字符串
3、對於url3字符串(結果和url2的相同:因為port默認為80,且為80時輸出空字符串,保持與location對象的port屬性一致)
4、對於url4字符串
5、對於url5字符串
6、對於url6字符串(注意:結果把查詢字符串對象也輸出了)
7、同理對於url7
尼瑪^_^,終於截完7個圖了,手都軟了。。。。突然發覺忘記吃飯了
結語:又花了2個多小時從編寫代碼到寫完blog,(~ o ~)~zZ,對於該題的實現過程,可能有一些因素沒考慮到,也可能有各種bug,希望得到大家的建議,不過感覺騰訊的筆試題分量真的很高,接下來的日子要好好復習計算機基礎知識了,為了9月份的tencent校園招聘,哥也要奮斗了,雖然起點落后了很多,不過喜歡努力為目標奮斗的過程,做一個有夢想的人吧!good good study,day day up~