這是我在面試大公司時碰到的一個筆試題,當時自己雲裡霧裡的胡寫了一番,回頭也曾思考過,最終沒實作也就不了了之了。
昨天看到有網友說面試中也碰到過這個問題,我就重新思考了這個問題的實作方法。
對于想進大公司的童鞋,我想多說兩句,基礎知識真的很關鍵。平時在工作中也深刻體會到,沒有紮實的基礎知識,簡單問題容易複雜化。
因為存在
indexOf
的方法,是以自定義方法寫成 indexof
,友善對比。
對于
Array.indexof()
方法的實作,主要考察的就是原型繼承的知識。
通過
Array.prototype.indexof = function(){}
就可以給 Array
添加一個方法,實際工作中不推薦這樣做。
剩下的就是數組元素比對的問題,就不多說了,雖然不難,但是做的過程中也遇到了不大不小的問題。
最終代碼如下
Array.prototype.indexof = function(searchElement, fromIndex) { var len = this.length; // 首先判斷 fromIndex 是否合法 if (fromIndex == null) { fromIndex = 0; } if (fromIndex < 0) { fromIndex = len - 1; } // 循環判斷 searchElement 是否與數組内元素相等 for (var i = fromIndex; i < len; i++) { // 如果相等則傳回目前索引值 if (searchElement === this[i]) { return i; } } return -1 }
View Code
測試數組
var arr = ['a', '0', 0, 'a'];
試了試,基本和原生方法差不多,沒有太明顯的bug,但是總覺得自己的代碼有些不夠簡練,邏輯不夠嚴謹。如果文章到此就結束了,顯的有點水。
翻 MDN 的時候看到了一個關于 Array.indexOf() 方法的 polyfill,因為該方法是 ECMAScript 第五版中實作的,是以沒有原生支援的時候就會用如下方法實作。也就是這個問題有了一個官方答案。我認為大家可以先不看官方代碼,自己嘗試着寫一寫,然後再對比答案就會發現自己的不足。
// Production steps of ECMA-262, Edition 5, 15.4.4.14 // Reference: http://es5.github.io/#x15.4.4.14 if (!Array.prototype.indexOf) { Array.prototype.indexOf = function(searchElement, fromIndex) { var k; // 1. Let o be the result of calling ToObject passing // the this value as the argument. if (this == null) { throw new TypeError('"this" is null or not defined'); } var o = Object(this); // 2. Let lenValue be the result of calling the Get // internal method of o with the argument "length". // 3. Let len be ToUint32(lenValue). var len = o.length >>> 0; // 4. If len is 0, return -1. if (len === 0) { return -1; } // 5. If argument fromIndex was passed let n be // ToInteger(fromIndex); else let n be 0. var n = +fromIndex || 0; if (Math.abs(n) === Infinity) { n = 0; } // 6. If n >= len, return -1. if (n >= len) { return -1; } // 7. If n >= 0, then Let k be n. // 8. Else, n<0, Let k be len - abs(n). // If k is less than 0, then let k be 0. k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); // 9. Repeat, while k < len while (k < len) { // a. Let Pk be ToString(k). // This is implicit for LHS operands of the in operator // b. Let kPresent be the result of calling the // HasProperty internal method of o with argument Pk. // This step can be combined with c // c. If kPresent is true, then // i. Let elementK be the result of calling the Get // internal method of o with the argument ToString(k). // ii. Let same be the result of applying the // Strict Equality Comparison Algorithm to // searchElement and elementK. // iii. If same is true, return k. if (k in o && o[k] === searchElement) { return k; } k++; } return -1; }; }
仔細看了看官方代碼,思路清晰,邏輯嚴謹,代碼簡潔,再回頭看看自己的代碼,真是慘不忍睹,實在很慚愧。這個問題不難,但是通過閱讀官方代碼,發現這其中有很多值得學習的地方,尤其是條件判斷是否全面,考慮問題是否周到。我從不敢以程式員自诩,至少現在看來自己還不夠格。解決一個問題很簡單,但是能不能把問題解決好就是能力的展現。
感謝您的閱讀,如果您對我的文章感興趣,可以關注我的部落格,我是叙帝利,下篇文章再見!
開發低代碼平台的必備拖拽庫 https://github.com/ng-dnd/ng-dnd
基于 Angular Material 的中背景管理架構 https://github.com/ng-matero/ng-matero
Angular Material Extensions 擴充元件庫 https://github.com/ng-matero/extensions
仿 Windows 照片檢視器插件 https://github.com/nzbin/photoviewer
仿 Windows 照片檢視器插件 jQuery 版 https://github.com/nzbin/magnify
完美替代 jQuery 的子產品化 DOM 庫 https://github.com/nzbin/domq
簡化類名的輕量級 CSS 架構 https://github.com/nzbin/snack
與任意 UI 架構搭配使用的通用輔助類 https://github.com/nzbin/snack-helper
單元素純 CSS 加載動畫 https://github.com/nzbin/three-dots
有趣的 jQuery 卡片抽獎插件 https://github.com/nzbin/CardShow
懸疑科幻電影推薦 https://github.com/nzbin/movie-gallery
鍛煉記憶力的小程式 https://github.com/nzbin/memory-stake