面試-手撕代碼(2)

2021-03-02 Coding Faner

12月的北京,寒氣逼人。網際網路行業的人才越來越多,競爭壓力越來越大。在從業人員越來越優秀的情況下,你的不進步就意味著退步。所以,只有多學習,多總結,才能在網際網路的寒冬中生存下來。以下是手撕代碼系列的第二篇,謹獻給大家,望和大家共同進步。

十 手寫Array.prototype.map

在寫map之前,我們可以先來看一個經典的面試題。

['1', '2', '3'].map(parseInt) what & why ?

不賣關子,這個面試題的答案是[1, NaN, NaN]。為什麼呢?

我們先來看mdn上對map參數的介紹:

callback

生成新數組元素的函數,使用三個參數:

thisArg可選

執行 callback 函數時值被用作this。

在這道題中,map的參數是parseInt,我們再來看看mdn上parseInt的參數,

這個時候,我們結合map和parseInt各自的參數,可以知道map的返回值為

[parseInt(1, 0), parseInt(2, 1), parseInt(3, 2)],radix為0時,且string參數不以「0x」和「0」開頭時,按照10為基數處理。這個時候返回1。基數為1(1進位)表示的數中,最大值小於2,所以無法解析,返回NaN。基數為2的時候同理。

言歸正傳,我們的目標是實現一個Array.prototype.map,以下便是實現的代碼:

 'use strict' Array.prototype.map = function (fn, context) {   if (this === null || this === undefined) {     throw new Error('Array.prototype.map called on null or undefined');    }        if (typeof fn !== 'function') {      throw new Error(`Uncaught typeError: ${fn} is not a function`);     }     const results = [];     const list = this;     for (let i = 0; i < list.length; i++) {       const ret = fn.call(context, list[i], i, list);          results.push(ret);     }       return results; }
console.log([1].map()); console.log(Array.prototype.map.call(undefined)); console.log([1, 2, 3, undefined].map(item => item)); console.log([1, 2, 3, undefined].map(item => item * 2));

十一 call
  'use strict'      Function.prototype.call = function(context, ...args){    const fn = Symbol('fn');     if(context === null || context === undefined){      fn(context);    }          if(typeof context !== 'object' && context !== undefined){      context = {};    }    context[fn] = this;    const results = context[fn](...args)    delete context[fn];    return results;  }    function Test(){    this.name = 'breakair';  }    Test.prototype.sayName = function(){    return `Hello, ${this.name}`;  }  const obj = {name: 'Bob'};    const test = new Test();    console.log(test.sayName());     console.log(test.sayName.call(obj));     console.log(test.sayName.call(undefined)); 

十二 bind

實現bind的過程中,我們需要注意在構造函數的情況下,bind的構造出來的實例的指向問題。

  Function.prototype.bind = function(context, ...args){    const fn = this;    function Fn(...inner){            return fn.call(this instanceof Fn? this: context, ...args, ...inner);    }    Fn.prototype = Object.create(fn.prototype);    return Fn;  }    const obj = {    name: 'breakair',    sayName: function(){      return `Hello, ${this.name}`;    }  };  var name = 'Bob';    console.log(obj.sayName());     const sayName = obj.sayName;    console.log(sayName());     const sayName1 = obj.sayName.bind(obj);    console.log(sayName1());       function LateBloomer() {    this.petalCount = Math.ceil(Math.random() * 12) + 1;  }
LateBloomer.prototype.bloom = function() { window.setTimeout(this.declare.bind(this), 1000); };
LateBloomer.prototype.declare = function() { console.log('I am a beautiful flower with ' + this.petalCount + ' petals!'); };
var flower = new LateBloomer(); flower.bloom(); function Point(x, y) { this.x = x; this.y = y; }
Point.prototype.toString = function() { return this.x + ',' + this.y; };
var p = new Point(1, 2);
console.log(p.toString());
var YAxisPoint = Point.bind(null, 0);
var axisPoint = new YAxisPoint(5); console.log(axisPoint.toString());
console.log(axisPoint instanceof Point); console.log(axisPoint instanceof YAxisPoint); console.log(new YAxisPoint(17, 42) instanceof Point);

十三  對象的深拷貝
  function deepCopy(obj){    if(typeof obj !== 'object' || obj === null){      return obj    }        if(Array.isArray(obj)){       const results = [];      for(let i = 0; i < obj.length; i++){        results[i] = deepCopy(obj[i]);      }      return results;    } else {      const results = {};      for(const key in obj){        if(obj.hasOwnProperty(key)){          results[key] = deepCopy(obj[key]);        }      }      return results;    }  }    const oriObj = {    val: 1,    children: {      fn: () => {        console.log('hello, this is copy')      },      names: [1, 2, 3],    }  }  const newObj = deepCopy(oriObj);  console.log(newObj);

十四 實現一個簡單的事件監聽
class EventEmitter{        constructor(){      this.events = new Map();    }        on(type, fn){      this.events.set(type, fn);    }        emit(type, ...args){      const handler = this.events.get(type);      handler.call(this, ...args);    }  }      let emitter = new EventEmitter()    emitter.on('ages', age => {    console.log(age)  })    emitter.emit('ages', 18)  

十五 雙向數據綁定
let obj = {}let input = document.getElementById('input')let span = document.getElementById('span')Object.defineProperty(obj, 'text', {  configurable: true,  enumerable: true,  get() {    console.log('獲取數據了')  },  set(newVal) {    console.log('數據更新了')    input.value = newVal    span.innerHTML = newVal  }})input.addEventListener('keyup', function(e) {  obj.text = e.target.value})

十六 簡單路由的實現
class Route{  constructor(){        this.routes = {}        this.currentHash = ''        this.freshRoute = this.freshRoute.bind(this)        window.addEventListener('load', this.freshRoute, false)    window.addEventListener('hashchange', this.freshRoute, false)  }    storeRoute (path, cb) {    this.routes[path] = cb || function () {}  }    freshRoute () {    this.currentHash = location.hash.slice(1) || '/'    this.routes[this.currentHash]()  }}

十七 實現懶加載
<ul>  <li><img src="./imgs/default.png" data="./imgs/1.png" alt=""></li>  <li><img src="./imgs/default.png" data="./imgs/2.png" alt=""></li>  <li><img src="./imgs/default.png" data="./imgs/3.png" alt=""></li>  <li><img src="./imgs/default.png" data="./imgs/4.png" alt=""></li>  <li><img src="./imgs/default.png" data="./imgs/5.png" alt=""></li>  <li><img src="./imgs/default.png" data="./imgs/6.png" alt=""></li>  <li><img src="./imgs/default.png" data="./imgs/7.png" alt=""></li>  <li><img src="./imgs/default.png" data="./imgs/8.png" alt=""></li>  <li><img src="./imgs/default.png" data="./imgs/9.png" alt=""></li>  <li><img src="./imgs/default.png" data="./imgs/10.png" alt=""></li></ul>

let imgs =  document.querySelectorAll('img')let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeightfunction lazyLoad () {    let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop  for (let i = 0; i < imgs.length; i ++) {        let x = clientHeight + scrollTop - imgs[i].offsetTop        if (x > 0 && x < clientHeight+imgs[i].height) {      imgs[i].src = imgs[i].getAttribute('data')    }  }}

十八 rem的實現
setRem()function setRem () {  let doc = document.documentElement  let width = doc.getBoundingClientRect().width  let rem = width / 75  doc.style.fontSize = rem + 'px'}addEventListener("resize", setRem)

相關焦點

  • 想去面試?這10道最高頻的手撕代碼題都會了嗎?
    下面這10道最高頻的手撕代碼面試題都會了嗎?相信我,徹底掌握以下這10道題的解法,你順利做出手撕代碼面試題目的概率至少不低於50%。1,快速排序題目形式:手寫一下快速排序算法。題目難度:中等。出現概率:約50%。手寫快排絕對是手撕代碼面試題中的百獸之王,掌握了它就是送分題,沒有掌握它就是送命題。
  • 面試手撕算法系列:二分法
    最近春招開始了,面試面著面著一言不合就開始手撕代碼手撕就手撕,接下來我打算寫幾個專題講講面試中手撕的常見題目 這些都是LeetCode上有的題目 手撕無非就是 樹、鍊表、二分、字符串這些常用的數據結構二分法查找,也稱為折半法,是一種在有序數組中查找特定元素的搜索算法。
  • 阿里員工吐槽:手撕AVL和紅黑樹,字節跳動面試真的太無聊!
    字節跳動面試真的是太無聊了,不知道你們工作中哪裡需要手撕AVL和紅黑樹,哪裡需要把指針移動來移動去的。個人覺得聰明和背題是兩回事,字節面試對你的工作經驗和業務絲毫不關心,去面試,代碼沒讓寫,但是讓總結說這兩種樹的優缺點和設計思路異別。個人觀點覺得,學東西最終是為了致用,而不是為了卷面成績。如果以後被撈屍,我打算先請教他們這些問題。
  • 手撕SQL | 必知必會5道SQL面試題
    請根據各小題的需求,用代碼實現輸出第一個名字(First_name)包含『o』的所有僱員信息,並按薪資降序排列;參考代碼:2.參考代碼:2.的能力考察同學們的審題是否細緻、考查理解業務的能力將業務需求轉換成構建SQL語句、並得到分析結果的能力需要同學們熟記SQL子句的書寫順序和運行順序重點考察大家基本功,手撕
  • 【別笑】手撕吊打面試官系列面試題
    必備面試題js基礎1.用js列印一個乘法表這一題面試官考察的是你關於js的列印相關基礎api的熟悉程度,以及基本的數學常識,送分題console.log(`1*1=12*1=2 2*2=43*1=3 3*2=6 3*3=94*1=4 4*2=8 4*3=12 4*4=16
  • 微服務專題|Naocs 源碼設計的精髓就在這了,給你一個手撕面試官的機會
    微服務專題|Naocs 源碼設計的精髓就在這了,給你一個手撕面試官的機會Nacos 如何扛住高並發讀寫?最近經常閱讀源碼,發現大部分框架在解決並發讀寫的時候,都會使用使用COW的思想來解決;nacos也不例外。
  • 清華天才王垠受邀面試阿里,卻大談自己的博客,手撕P10面試官趙海平
    【清華天才王垠受邀面試阿里P9崗位,被斃後網上發文爆內情,手撕P10面試官趙海平】昨天看了這位清華天才王垠去阿里巴巴面試P9崗位新聞,我感覺人生觀又被刷新了!我不是做網際網路的,我可以算做人力資源的。
  • 清華天才王垠受邀面試阿里P9被斃後手撕P10面試官趙海平!
    之所以猶豫是因為,在我的職業生涯中面試過一兩千人了,從來沒有在事後回應過面試者,因為面試訓練裡告誡面試官最好的做法是不回應,而且揭露細節和具體原因是違背公司規定的,但是我理解和同情王垠的感受和面試失敗的挫敗感,本著愛才惜才的動機,就簡單的解釋一下吧,只不過依然不能違法的揭露過多的細節,只能針對有疑問的地方稍加解釋,見諒了。
  • 快手大數據崗位招聘面試題分享
    學長1快手:視頻面試1)一面:50分鐘(1)介紹項目(2)Flink為什麼用aggregate()不用process()(3)自定義UDF,UDTF實現步驟,有哪些方法?2)二面:1小時(1)手撕SQL ①A-天極增量表: uid,module_name,location,date 目標-B全量表: uid,module_name,first_entry_date,first_location 找出兩個第一次插入到B表 ②user:uid,age,date
  • 一個妹子的後臺面試經驗總結(螞蟻金服+美團+攜程+滴滴+....)
    《大話設計模式》《mysql必知必會》《程式設計師面試金典》《java並發編程實戰》《計算機作業系統第三版》《計算機網絡》都看了一遍,《深入理解java虛擬機》看了兩遍。《java編程思想》《Java數據結構和算法中文第二版》《Spring技術內幕:深入解析Spring架構與設計原理(第2版)》《Struts2 in action中文版》《tcp詳解卷一》挑的重點看。
  • 滴滴Android崗面經分享:面試真題+經驗總結
    1.首先是自我介紹2.從筆試的算法題入手,詳細講講自己的思路。然後分析一下時間,空間複雜度提出優化和改進的方法3.再加一道手撕算法題4.考察了http,tcp等計算機網絡知識5.涉及了一小部分的作業系統6.常見的數據結構包括堆棧隊列等結構java中對應的類:從array,arrayList,linkedList,Queue, PriorityQueue,Deque, stack等等講了一遍
  • 面試官問:請拿出一段體現你水平的代碼時,該如何回答?
    (經評論區大神指導,修改了結尾)把這段代碼給他看既有多線程的知識,又有排序方法。,少不了羞辱一下面試官爽一下。如果問這種問題,一般大約是3年經驗以下的面試。這種呢,一般處理有兩種。第一種是有備而來的面試者,你最好去面試的時候帶一個百寶箱:兩份簡歷,一兩張紙印了你最擅長的代碼,如果更準備充足點,帶上你的筆記本,或者平板,兩者都要能上網或者已經緩存了你的作品。肯定有人會說的,傻蜜蜂,他們沒我的簡歷,面試我做什麼,我只要人去就是看得起他們。
  • 機打手撕發票 都是正式發票
    讀者馬先生:我到飯店、餐廳吃飯,為什麼有的地方用餐後開具通用機打發票、有的地方給手撕的通用定額(有獎)發票?這兩種發票效用一樣嗎?  「有事您言語」專欄記者:市地方稅務局徵管處王海勇介紹,通用機打發票和手撕通用定額(有獎)發票都是國家有效的正式發票。通用機打發票分為平推式發票和卷式發票兩種。
  • 乾貨 | 算法和編程面試題精選TOP50!(附代碼+解題思路+答案)
    這次營長表示要翻 Java 的牌子啦~ 應大家的強烈反饋,我們找了一套 Java 語言的算法和編程的面試題。這份面試資源主要包含五部分內容:數組、鍊表、字符串、二叉樹和重要算法(如排序算法)的編程面試題,其中每部分內容我們都列出了一些最常被問到的熱門問題,並且在每個題目後給出了可以參考的解決思路和代碼,因為題目較多,我們沒有羅列所有的方法和代碼,只給出了訪問地址。相信大家在掌握了這些內容後,一定可以提升實力、信心大增。
  • 五分鐘帶你手撕九大經典排序算法
    排序是一個歷史話題,目前已有很多非常成熟的排序算法,雖然在 ACM 比賽中並不會讓你具體實現一個排序算法,但是在面試當中,或者在和別人吹牛的過程中,可以口述,或者手撕一個排序算法。本文將列舉一些常用的算法。
  • NLP中文面試學習資料:面向算法面試,理論代碼俱全,登上GitHub趨勢榜
    這裡有一份NLP面試大全,全中文教學,囊括機器學習及NLP算法面試中常考的知識點,還有算法實戰代碼,實乃算法工程師求職路上,必備良品。宜入門,亦宜複習。還登上了GitHub趨勢榜。學習目錄這份學習資料分為機器學習、深度學習和NLP三個部分。
  • 漫畫:美團面試題(TOPK:求第K個最大的元素)
    示例 1:輸入: [3,2,1,5,6,4] 和 k = 2輸出: 5示例 2:輸入: [3,2,3,1,2,4,5,5,6] 和 k = 4輸出: 4堆在算法題目中的應用主要包括以下幾點:
  • 飯館手撕發票蓋別家印章 稅務部門將介入調查
    店員無奈提供手撕發票,然而這張手撕發票可能為假票。 天津北方網訊:顧客就餐索要發票遭飯館拒絕,店員直指菜單稱「不開發票」早就寫明了。記者調查中,堅持向飯館索要發票。店員無奈提供手撕發票,然而這張手撕發票可能為假票。
  • 面試題:請用代碼實現ip地址與int之間互換?
    面試那些事兒面試官:Ipv4地址可以轉為Long類型的數字知道吧?你寫一下這個轉換的代碼。對計算機基礎逐漸模糊的小黃一臉懵逼,畢竟工作中很少會用到,只記得ip地址和整數是可以相互轉換的,但是從來沒有自己實現過。於是在大腦中飛速計算。過了一會,思路出現了:ip 地址分為四段,每段都是 0~255 之間的數,每段可以用 8 位來裝下它,4x8=32位,也就是可以將ip地址轉為 32 位的整數。咦?
  • NLP、CV、語音相關AI算法工程師面試問題、代碼、簡歷模板、知識點等資源整理分享
    本資源整理了機器學習、深度學習、算法工程師等AI相關崗位面試需要知識點,常見代碼實戰(分為C/C++和python版本)、常見問題,簡歷模板、比賽/競賽相關的資源,分享給需要的朋友。        o資料        o代碼實戰    •深度學習        o面試        o資料        o代碼實戰 Pytorch        o代碼實戰 Tensorflow        o網課    •C/C++    •Python