摘要:為了避免它,只需分配將要使用的必要構造函數。示例對于此示例,就需要保持父構造函數繼續正常工作。結論手動設置或更新構造函數可能會導致不同且有時令人困惑的后果。為了防止它,只需在每個特定情況下定義構造函數的角色。
hr小姐姐說一共有1輪筆試 + 3輪技術面 + 1輪hr面,面試地點在中關村天使大廈,崗位是1-3年前端筆試
筆試分為多選 簡答 判斷 手寫代碼四部分,下面只寫了印象比較深的幾道。
多選1、position為relative的元素可以使用top和left進行定位嗎
答:可以。
我自己沒見過這種寫法,就沒敢選,然后錯。
2、以下哪個是加密算法
答:RES、DES。
md5不算加密算法。
這部分題目是給出代碼,讓你寫輸出
1、
setTimeout(() => {console.log(1)}) const promise = new Promise(resolve => { setTimeout(() => {console.log(2)}) resolve() }) promise.then(() => {console.log(3)})
答:312。
考察macro/micro task
2、
for(var i = 1; i < 3; i++) { setTimeout(() => {console.log(i)}) }
答:3 3
考察異步,這個題簡直是必考題
變種:
for(let i = 1; i< 3; i++) { setTimeout(() => {console.log(i)}) }
答:1 2
用let的話就會每輪循環都是一個嶄新的i
3、
function A() { this.a = "hi" console.log(this.a) } A.prototype.a = "hello" const a = new A() console.log(a.a)
答:hi hi
考察原型鏈,A.prototype.a = "hello",修改的是a原型上的a屬性,與a本身的a屬性無瓜。
瀏覽器運行截圖
4、
[] == false
答:true
考察類型轉換,雙等運算兩邊先轉換為Number
5、
[1,2,3].push(4)
答:4
考察常用函數返回值, 數組的push和unshift都返回最新數組的長度
判斷就5道題,挺簡單的,沒啥印象
手寫代碼手寫一個節流函數,這個網上一搜一大把就不說了
一面筆試寫了大概30-40分鐘,一面的面試官就來了,看答題情況的時候順便要求介紹一下自己,然后針對題目做了一些講解,然后開始問問題。
1、再手寫一個防抖,我寫了一個第一次觸發事件不會調用回調的,面試官又問如果希望首次也會調用怎么寫,代碼如下
var debounce = function(fn, delayTime, immediate) { var timeId; return function() { var context = this, args = arguments; if(immediate) { var callNow = !timeId; if(callNow) { fn.apply(context, args); } } timeId && clearTimeout(timeId); timeId = setTimeout(function() { fn.apply(context, args); }, delayTime) } }
然后還聊了一下時間戳和定時器的方式實現節流的不同,需要注意箭頭函數是不可以使用arguments對象的,所以返回的函數必須要寫成return function() {}
2、有什么實現深拷貝的方法嗎
??????我一開始以為他說api,就回答JSON.parse(JSON.stringfy())和MessageChannel,他問有什么問題嗎。我說不能解決復制函數和環的問題。他又問那你能自己實現一個嗎,繼續手寫代碼
function isObject(obj) { return obj !== null && typeof obj === "object" } function cloneDeep(obj) { let result = {} const keys = Object.keys(obj); for(let i = 0, len = keys.length; i < len; i++) { if(isObject(obj[keys[i]])){ result[keys[i]] = cloneDeep(obj[keys[i]]) } else { result[keys[i]] = obj[keys[i]] } } return resultset }
??????寫完之后他又問我應該如何判斷一個變量是數組,答Array.isArray()和Object.prototype.toString.call(arr) === "[object Array]",回來反思發現可能是寫深拷貝的時候忘記了數組的情況,然后他才問的判斷數組。
3、如何用css畫一個三角形
答:heigh: 0; width: 0; border: 100px, solid, transparent; border-bottom: 100px, solid, yellow;
4、怎么實現垂直居中
答:position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); 還有flex;
5、簡單說一下前端優化策略
答:減少請求,他:具體應該怎么減少,我:比如圖片懶加載,配置svg-sprite-loader打包一張svg圖面,然后就是減少dom操作,減少瀏覽器回流重繪次數,減少作用域鏈的查找,減少對象的深度查找。他:還有嗎。我:暫時想不起其它了
優化涉及的東西太多了,以后再多帶帶總結吧。
6、new一個對象的時候發生了什么
這個問題是講解筆試簡答第三題時候問的
正確答案:1.創建一個空對象; 2.設置創建對象的__proto__屬性的值為構造函數的prototype屬性的值; 3.將第一步創建的空對象作為this的上下文,執行構造函數代碼; 如果構造函數沒有返回對象,那么返回this
7、看你簡歷上寫最近在看vue源碼,那你知道nextTick咋實現的嗎
答:2.6的版本是promise,mutationObserver,setTimeout,setImmediate
??????至此面試官說一面差不多就到這里,算法啥的留給二面吧,他給我的一面評價是知識廣度不夠(因為筆試錯了比較多),但是感覺人比較有靈性,可以進入二面,然后就去叫下一個boss了。
二面??????二面面試官看起來比前一個要嚴厲好多,以為要問一些算法題,結果"一面反饋基礎不夠扎實,那我就再問一點" "GG"
1、import和require的區別
答:import輸出引用,require輸出拷貝。他:還有嗎。 我:不知道了。他:還有require是運行時加載,import是編譯時輸出接口。
2、說一下瀏覽器的事件傳播機制
答:不知道
正確答案: 事件傳播分為三個階段:捕獲,目標對象,冒泡。其中捕獲是事件對象從window派發到目標對象父級的過程;目標階段是事件對象派發到目標元素時的階段,如果事件類型指示不冒泡,那事件傳播在此階段終止;冒泡和捕獲相反,是以目標對象父級到window的過程。
3、手寫一個bind
答:不知道。
平時用的都是call和apply來改this,bind只用過一兩次,手寫call也看過,但是我連bind的參數是啥都沒印象,寫個錘子。
正確答案:
///使用call Function.prototype.cvBind = function() { var self = this var context = [].shift.call(arguments) var args = Array.from(arguments) return function() { return self.call(context, ...args) } } // 不用call Function.prototype.cvBind = function() { var context = [].shift.call(arguments) context.fn = this var args = [] var argument = [].slice.call(arguments, 0) for(var i = 0, len = argument.length; i < len; i++) { args.push("argument[" + i + "]") } return function() { var result = eval("context.fn(" + args + ")") delete context.fn return result } } // 測試 var obj = { a: "local", log: function(x, y) { console.log(this.a, x, y) } } var a = "window" obj.log("arg1", "arg2") var func = obj.log.cvBind(window, "arg1", "arg2") func()
需要注意不用call的版本需要拷貝一次arguments,不然return的函數中args數組里都是undefined,上面的代碼不考慮參數是引用類型變量。
4、寫一個繼承
答:不知道
正確答案:
4.1類式繼承,通過構造函數實現繼承
//父類 function Parent(name) { this.name = name || "parent" } Parent.prototype.say = function() { return this.name } //子類 function Child() {}
4.1.1 父類對象繼承
Child.prototype = new Parent("child") var child = new Child() child.say()
這種繼承方式,子類繼承父類自身屬性和父類原型上的屬性,但是缺點在于初始化父類對象指給子類原型時,并不能確定父類構造函數的初始化參數。
4.1.2 改造子類構造函數
function Child() { Parent.apply(this, arguments) }
弟中弟方法,只能繼承父類自身方法
4.1.3 共享原型
Child.prototype = Parent.prototype
弟中弟中弟,共享一個原型,子類修改會影響父類(然而面試的時候腦子里浮現的就是這種)
4.1.4 臨時構造函數
function inherit(Child, Parent) { var F = function() {} F.prototype = Parent.protoType Child.protoype = new F() }
利用一個空函數F()充當子類父類之間的代理,既可以實現父類原型屬性的繼承,也可以在子類原型上隨意拓展
使用Object.create()可以達到相同效果
Child.prototype = Object.create(Parent.prototype)
4.1.5 關于protptype.constructor
整理資料的時候,發現有些在繼承后又寫了一句Child.prototype.constructor = Child,有些就沒有。首先這個constructor時創建實例對象的構造函數的引用,然后就是這句話到底有用沒用,下面是ctrl cv自MDN的兩個例子以及結論
示例1:
function Parent() {}; function CreatedConstructor() {} CreatedConstructor.prototype = Object.create(Parent.prototype); CreatedConstructor.prototype.create = function create() { return new this.constructor(); } new CreatedConstructor().create().create(); // error undefined is not a function since constructor === Parent
在上面的示例中,將顯示異常,因為構造函數鏈接到Parent。為了避免它,只需分配將要使用的必要構造函數。
function Parent() {}; function CreatedConstructor() {} CreatedConstructor.prototype = Object.create(Parent.prototype); CreatedConstructor.prototype.constructor = CreatedConstructor; // set right constructor for further using CreatedConstructor.prototype.create = function create() { return new this.constructor(); } new CreatedConstructor().create().create(); // it"s pretty fine
示例2:
function ParentWithStatic() {} ParentWithStatic.startPosition = { x: 0, y:0 }; ParentWithStatic.getStartPosition = function getStartPosition() { return this.startPosition; } function Child(x, y) { this.position = { x: x, y: y }; } Child.prototype = Object.create(ParentWithStatic.prototype); Child.prototype.constructor = Child; Child.prototype.getOffsetByInitialPosition = function getOffsetByInitialPosition() { var position = this.position; var startPosition = this.constructor.getStartPosition(); // error undefined is not a function, since the constructor is Child return { offsetX: startPosition.x - position.x, offsetY: startPosition.y - position.y } };
對于此示例,就需要保持父構造函數繼續正常工作。
結論:手動設置或更新構造函數可能會導致不同且有時令人困惑的后果。為了防止它,只需在每個特定情況下定義構造函數的角色。在大多數情況下,不使用構造函數,并且不需要重新分配構造函數。
4.2 通過復制屬性實現繼承
淺拷貝和4.1.3的共享原型沒區別,深拷貝繼承之后修改父類,子類不會改變。都有問題不過也是一種思路,順帶一提。
5、跨域有哪些解決方案
答:iframe, jsonp, cors。他:用過jsonp嗎。答:沒有,用的都是cors。他:那說一下cors是怎么解決跨域問題的。我:不知道。他:那請求頭里有哪些相關的字段。我:(我知道你真的很給機會了但是對不起我是個菜雞我真的)不知道。他:用過nginx嗎。我:沒有。
正確答案:點這里
balabala一些客套話,問我有什么問題,我說沒有,然后結束。
路漫漫其修遠兮認識到差距也更有前進的動力,繼續加油
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/106266.html
摘要:這是一次失敗的面經但是吃一塹才能長一智不是嗎字節跳動校招面經前端開發崗一介紹以及項目經歷吧啦吧啦此處省略字面試官會從項目經歷入手,考察項目中遇到的難題,以及解決方法,強調個人的努力以及在解決過程中扮演的角色是主導還是參與。 這是一次失敗的面經……但是吃一塹才能長一智不是嗎? 字節跳動2019校招面經 - 前端開發崗(一) 1. 介紹以及項目經歷 吧啦吧啦……此處省略10000字 面試官...
摘要:春招前端實習面試記錄從就開始漸漸的進行復習,月末開始面試,到現在四月中旬基本宣告結束。上海愛樂奇一面盒模型除之外的面向對象語言繼承因為是視頻面試,只記得這么多,只感覺考察的面很廣,前端后端移動端都問了,某方面也有深度。 春招前端實習面試記錄(2019.3 ~ 2019.5) 從2019.1就開始漸漸的進行復習,2月末開始面試,到現在四月中旬基本宣告結束。在3月和4月經歷了無數次失敗,沮...
摘要:面試后面試后及時總結,有可能下一個面試官會問你同樣的問題。同時面試官也對我的未來技術發展提出了很多建議。總的來說,四面的氛圍并沒有想象得那么嚴肅,面試官也說面試得很愉快。 ...
摘要:為什么狀態需要經過最大報文段生存時間才能返回到狀態雖然按道理,四個報文都發送完畢,我們可以直接進入狀態了,但是我們必須假象網絡是不可靠的,有可以最后一個丟失。所以狀態就是用來重發可能丟失的報文。 1、TCP的三次握手和四次揮手 1.1 三次握手: 客戶端請求 -> 服務器響應 -> 客戶端確認收到響應,建立連接(保證網絡正常) showImg(https://segmentfault....
閱讀 3103·2021-11-22 09:34
閱讀 605·2021-11-22 09:34
閱讀 2456·2021-10-08 10:18
閱讀 3388·2021-09-22 15:57
閱讀 2600·2021-09-22 15:25
閱讀 2419·2019-08-30 15:54
閱讀 2132·2019-08-30 15:44
閱讀 1809·2019-08-29 11:18