引言html
牛客網這個前端筆試題庫,能夠說這60道是最基礎的了,也是考察的東西比較雜,有時間4天差很少就能夠刷完,鞏固基礎仍是有些用的。作完題回顧一上午就能夠過完一遍。如今我結合個人答案和參考的其餘人的答案,在這裏作一個總結,也是本身知識的整理結果。前端
封裝函數 f,使 f 的 this 指向指定的對象。
這裏給出三種寫法,哪一種均可以。正則表達式
// apply修改this做用域 function bindThis(f, oTarget) { return function () { return f.apply(oTarget,arguments) } } // call修改this做用域 function bindThis(f, oTarget) { return function (){ return f.call(oTarget,...arguments) } } // bind修改this做用域 function bindThis(f, oTarget) { return function (){ return f.bind(oTarget,...arguments)() } } // 或者直接簡寫 function bindThis(f, oTarget) { return f.bind(oTarget) }
相關知識點:數組
apply、call、bind區別緩存
apply、call、bind的做用都是修改執行上下文
apply、call都是返回函數當即執行的結果,其中apply第二個參數以後是數組,call第二個參數以後是單個的值。
bind返回的是函數,須要手動執行結果。第二個參數以後是單個的值。
獲取 url 中的參數服務器
- 指定參數名稱,返回該參數的值 或者 空字符串
- 不指定參數名稱,返回所有的參數對象 或者 {}
- 若是存在多個同名參數,則返回數組
輸入:
http://www.nowcoder.com?key=1&key=2&key=3&test=4#hehe key
數據結構輸出:[1, 2, 3]app
function getUrlParam(sUrl, sKey) { let newArr = [] let newObj = {} // 獲取?號後面#號前面的值 let query = sUrl.split('#')[0].split('?')[1] // 若是query存在 if (query) { let arr = query.split('&') for(let i = 0 ; i < arr.length; i++) { if (arr[i]) { arr[i] = arr[i].split('=') // 數組 if (sKey !== undefined) { if(arr[i][0] === sKey) { newArr.push(arr[i][1]) } // 對象 } else { if(arr[i][0] in newObj) { newObj[arr[i][0]].push(arr[i][1]) } else { newObj[arr[i][0]] = [arr[i][1]] } } } } // 判斷sKey有沒有值 if(sKey !== undefined) { switch(newArr.length) { case 0 : return '';break; case 1 : return newArr[0]; break; default: return newArr;break; } } else { return newObj } // 若是query不存在,判斷sKey是否存在,若是存在就返回空對象,若是不存在就返回空字符串 } else { return sKey !== undefined ? {} : '' } }
相關知識點:dom
url的組成部分函數
https://user:pass@www.baidu.com:80/index.html?type=1&name=2#haha
http/https
是協議
user:pass@
是登陸認證
www.baidu.com
是域名,服務器地址
:80
是端口號
/index.html
是請求資源文件路徑
?type=1&name=2
是查詢字符串,攜帶參數,給服務器傳的內容。
#haha
是哈希,片斷標識符
split方法
字符串分割成數組的方法,裏面的參數是以什麼分割,若是不傳就是空字符串爲分割,返回值是一個數組。
查找兩個節點的最近的一個共同父節點,能夠包括節點自身
輸入描述:
oNode1 和 oNode2 在同一文檔中,且不會爲相同的節點
function commonParentNode(oNode1, oNode2) { if(oNode1.contains(oNode2)) { return oNode1 } else { return commonParentNode(oNode1.parentNode,oNode2) } }
相關知識點:
contains API
查看dom元素包含關係,包含返回true,不包含返回false
參考MDN
根據包名,在指定空間中建立對象
輸入描述:
namespace({a: {test: 1, b: 2}}, 'a.b.c.d')
輸出描述:
{a: {test: 1, b: {c: {d: {}}}}}
function namespace(oNamespace, sPackage) { let scope = sPackage.split('.') let ns = oNamespace for(let i = 0; i< scope.length; i++) { // 若是對象中沒有該元素,或者不是對象,那麼就置爲空對象 if(!ns.hasOwnProperty(scope[i]) || Object.prototype.toString.call(ns[scope[i]]) !== '[object Object]') { ns[scope[i]] = {} } // 而後繼續往下找 ns = ns[scope[i]] } return oNamespace }
考察知識點:
hasOwnProperty / typeof / in / instanceof 的區別
- hasOwnProperty 是判斷對象自身有沒有某屬性,不包含原型鏈的方法。
- in 是判斷對象在自身和原型鏈上有沒有該方法。
- instanceof 是判斷對象在原型鏈上有沒有該方法。
- typeof 判斷操做數的類型,可是null也會判斷爲"object"
準確判斷某值的類型
Object.prototype.toString.call(123) === "[object Number]"
Object.prototype.toString.call('aaa') === "[object String]"
Object.prototype.toString.call(true) === "[object Boolean]"
Object.prototype.toString.call(undefined) === "[object Undefined]"
Object.prototype.toString.call(null) === '[object Null]'
Object.prototype.toString.call({}) === '[object Object]'
Object.prototype.toString.call([]) === '[object Array]'
Object.prototype.toString.call(Math) === "[object Math]"
Object.prototype.toString.call(new Date()) === "[object Date]"
Object.prototype.toString.call(new RegExp) === "[object RegExp]"
爲 Array 對象添加一個去除重複項的方法
輸入
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a', 'a', NaN]
輸出
[false, true, undefined, null, NaN, 0, 1, {}, {}, 'a']
這個題,狗就狗在,還有NaN
// 方法一:終極思路 Array.prototype.uniq = function () { return [...new Set(this)] } // 方法二:普通思路,遍歷以後比較值 Array.prototype.uniq = function () { let arr = [] let flag = true this.forEach(value => { // == -1 有兩種狀況,一種是NaN,一種是有相同值 if(arr.indexOf(value) === -1) { // 若是是NaN if(value !== value) { // flag是標記,第一個NaN就進,以後的就不進去 if(flag){ arr.push(value) flag = false } } else { arr.push(value) } } }) return arr }
相關知識點:
uniq方法中的this指向哪裏?
Array構造函數的原型方法中的this指的是數組實例。
Set的特性
Set存儲的成員是惟一的,不是重複的,若是有重複會自動過濾掉.
ES6(七)—— Set & Map
(NaN === NaN) => false
NaN : is not a number,不等於本身
typeof NaN => number
Object.prototype.toString.call(NaN) => "[object Number]"
ES6 新增方法:Number.isNaN() 用來判斷是否屬於數字
用 JavaScript 實現斐波那契數列函數,返回第n個斐波那契數。 f(1) = 1, f(2) = 1 等
斐波那契數列基本學js都會,1 1 2 3 5 8 13,後一個是前兩個的和。
// 方法一:遞歸思路 function fibonacci(n) { if(n === 0) return 0 if(n === 1 || n === 2) return 1 return fibonacci(n-1) + fibonacci(n-2) } // 方法二:迭代思路 function fibonacci(n) { let num1 = 1 let num2 = 1 let sum = 0 for(let i = 3; i <= n; i++) { sum = num1 + num2 num1 = num2 num2 = sum } return sum } // 上面寫法能夠過oj,可是若是數字大點就超級慢,使用緩存很可 // 方法三:遞歸優化思路 function fibonacci(n,cache = {}) { // 有緩存就直接讀緩存 if(n in cache) return cache[n] if(n === 1 || n === 2) { cache[n] = 1 return 1 } // 沒有緩存算完以後存入緩存 let temp = fibonacci(n-1, cache) + fibonacci(n-2,cache) cache[n] = temp return temp }
相關知識點:
題目描述
按所給的時間格式輸出指定的時間
格式說明
對於 2014.09.05 13:14:20
yyyy: 年份,2014
yy: 年份,14
MM: 月份,補滿兩位,09
M: 月份, 9
dd: 日期,補滿兩位,05
d: 日期, 5
HH: 24制小時,補滿兩位,13
H: 24制小時,13
hh: 12制小時,補滿兩位,01
h: 12制小時,1
mm: 分鐘,補滿兩位,14
m: 分鐘,14
ss: 秒,補滿兩位,20
s: 秒,20
w: 星期,爲 ['日', '一', '二', '三', '四', '五', '六'] 中的某一個,本 demo 結果爲 五輸入
formatDate(new Date(1409894060000), 'yyyy-MM-dd HH:mm:ss 星期w')輸出
2014-09-05 13:14:20 星期五
function formatDate(t,str) { let year = ''+t.getFullYear() let month = t.getMonth() + 1 let day = t.getDate() let hour = t.getHours() let minutes = t.getMinutes() let second = t.getSeconds() let week = ['日','一','二','三','四','五','六'] let date = { 'yyyy': year, 'yy': year.slice(2), 'MM': ten(month), 'M': month, 'dd': ten(day), 'd': day, 'HH': ten(hour), 'H': hour, 'hh': ten(hour % 12), 'h': hour % 12, 'mm': ten(minutes), 'm': minutes, 'ss': ten(second), 's': second, 'w': week[t.getDay()] } for(let key in date) { str = str.replace(key,date[key]) } return str } // 不足10的前面要加0 let ten = num => num >= 10 ? num : '0' + num
考察知識點:
題目描述
若是第二個參數 bUnicode255For1 === true,則全部字符長度爲 1
不然若是字符 Unicode 編碼 > 255 則長度爲 2
輸入
hello world, 牛客', false
輸出 17
function strLength(s, bUnicode255For1) { if(bUnicode255For1) return s.length; let len = s.length for(let i = 0; i < s.length; i++) { if(s[i].charCodeAt() > 255) len++ } return len }
相關知識點:
題目描述
判斷輸入是不是正確的郵箱格式
考察正則的一道題目,方法也是多種多樣,這裏只有一種簡單的參考。
// ^ 表示開頭 // [] 表示匹配字符的範圍 // \w 表示正常符號 [0-9a-zA-Z_] // \. 是對任意符.進行轉義,表示字符. // + 表示前面的表達式,一次到屢次 function isAvailableEmail(sEmail) { return /^[\w\.]+@\w+\.\w+/.test(sEmail) }
相關知識點:
題目描述
將 rgb 顏色字符串轉換爲十六進制的形式,如 rgb(255, 255, 255) 轉爲 #ffffff
- rgb 中每一個 , 後面的空格數量不固定
- 十六進制表達式使用六位小寫字母
- 若是輸入不符合 rgb 格式,返回原始輸入
輸入 :'rgb(255, 255, 255)'
輸出 :#ffffff
function rgb2hex(sRGB) { // 正則匹配獲取三個數值 let reg = sRGB.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)/) if(!reg) return sRGB; // 字符串拼接 let str = '#' for(let i = 1; i < reg.length; i++) { // 將字符串轉成數字 let m = parseInt(reg[i]) if (m >= 0 && m <= 255) { // 而後轉化成16進制 str += (m >= 16 ? m.toString(16) : '0' + m.toString(16)) } else { return sRGB } } return str }
相關知識點:
toString的進制轉換
顏色是16進制,因此toString(16)能夠獲得結果
注意:必定要理解以後去程序裏面運行一遍。