杭州17屆前端期待加入一個更好的團隊

最近看到有人分享16屆前端進阿里(前端學習羣的羣主),17屆前端杭州收割offer(優秀的路人)。 恰好同爲17屆的我最近也很輕鬆拿了2個offer,可是我看到他們寫的題目回答並非很詳細,因此強迫症的我也想來和你們分享下,我會把全部沒掛掉的和掛掉的都分享出來,遇到的每一道題目都作詳細的分析,因此文章有點長哦。javascript

長文慎入哈,可是有酒有故事,小板凳我都給你搬好啦,快坐下!css

故事開始咯~html

原本想等過完年回來再換工做的,可是前段時間有獵頭在簡書私信我,說看個人文章寫得還行,問我想不想換工做。 而後我就更新了簡歷,發過去了,邀請我面試,可是這家公司在北京 /西安,後來就沒去,可是故事就此開始了,這反而促使我走上了換工做的道路。前端

貼一下自認爲寫得不錯的幾篇文章:vue

CSS3動畫卡頓性能優化解決方案html5

深度剖析0.1 +0.2===0.30000000000000004的緣由java

如何解決0.1 +0.2===0.30000000000000004類問題node

記一次簡單的DOM XSS攻擊實驗python

你真的理解==和===的區別嗎?react

經典CSS坑:如何完美實現垂直水平居中?

本身從大三暑假實習到如今工做半年多,接近快1.5+年的時間,一門心思扎到前端開發領域,高強度式的工做和學習,買書啃書,寫代碼看代碼,寫博客看博客,提問題回答問題,投入了幾乎是大一到大三學習時間總和的時間學習前端開發。

最近陰差陽錯開始筆試,面試,雖然都沒怎麼準備,可是很輕鬆就收穫了一家阿里子公司,一家浙大系公司的offer,再加上昨天被第三家面試官的讚揚,以前的妄自菲薄一下煙消雲散。

因爲本身此次換工做,但願可以在一家公司呆至少2年以上,很是但願能和一幫對前端技術有看法有思考有追求的小夥伴們,一塊兒去探索鑽研有趣的前端世界。因此我決定嘗試更多的面試,加入到一個更適合本身的團隊。

同時也但願經過這篇面試分享,可以給和我同樣努力的前端小夥伴們一些鼓勵,也但願可以把最真實的本身展示給你們。

面試1 - offer1 天道酬勤,付出終有回報

拒絕了第一家主動找到個人公司後,又有家阿里子創業公司在 BOSS 直聘裏私信我,而後抱着測試水平的心態面了。 現場筆試不怎麼樣,可是他們看到我簡書文章還算能夠,就讓我重作了一遍題目: 一些特別棒的面試題[0], 最後一道單詞與字符串匹配的題的拓展,都是面試官一步步引導我去深刻的,感受學習到不少。

沒想到結果是比較讓人驚喜的,前輩說個人學習能力比較強,因此願意給我這個機會,給的薪資比如今高 2K,關鍵是據說有許多項目能夠作,聽說面試個人老闆之前也是在阿里的技術專家。

貼一下面試題和個人回答。

1.說一下你熟悉的設計模式
2.說一下你理解的模塊機制
3.MVVM原理
4.最熟悉的框架路由機制
5.狀態管理
6.統計字符串中單詞出現次數
複製代碼

1.說一下你熟悉的設計模式

我最熟悉的設計模式:工廠模式(ES5),組件設計模式(ES6) 工廠模式(ES5,基於prototype。此例中基類Base,子類Factory)

var Factory = function () {
    if(!(this instanceof Factory)){
        return new Factory();
    }
}
Factory.prototype = Object.assign(new Base(), {
    version: '0.0.1',
    defaultOption:{
        title:'標題'
    },
    init:function (cfg) {
        this.title = cfg.title || '';
        this.currentOption = Object.assign(this.defaultOption,{
           //...
        })
    },
    render: function () {
        var option = this.currentOption;
        this.chart.setOption(option);
    },
    showTitle: function () {
        this._showTitle();
    }
})
複製代碼

組件設計模式(ES6,基於class,方便繼承和初始化,也是React組件的推薦寫法,我比較喜歡。此例中父類Compnent,子類Retrive)

class Retrive extends Component {
    constructor (props) {
        super(props);
        this.state = {
            name:''
        };
        this.getRemoteData = this.getRemoteData.bind(this);
    }
    getRemoteData (data) {
        this.state.retriveResult = data;
    }
    render(){
        return (
            <div className="Retrive">
                <Button name="search" onClick={this.getRemoteData}>查詢</Button>
            </div>
        );
    }
}
複製代碼

2.說一下你理解的模塊機制

AMD: 異步模塊加載規範。 a.js,定義一個依賴jQuery和echrts的組件。

define(['jquery', 'echarts'], function ($, echarts) {
  var AMD = function(){}
  AMD.prototype = {
       title:'',
        foo: function(){}//AMD類或者繼承AMD類的子類的屬性
  }
  function bar(){}//返回,公共屬性
   function baz(){} //未返回,私有屬性
  return {
       main:AMD,
       bar: bar
  }
});

複製代碼

若是b.js依賴a.js,能夠這樣

define(['./a'], function (a) {
     //調用構造函數,foo
     var instance_amd = new a.main();
     instance_amd.foo()
      //調用bar
     a.bar()
});
複製代碼

ES6 modules: 和python的包機制很相似,導入import,導出export。

1.場景:vue,react推薦機制,須要babel轉義成es5以兼容瀏覽器。
2.關於import...(from...)
①.import...from...的from命令後面能夠跟不少路徑格式,若只給出vue,axios這樣的包名,則會自動到node_modules中加載;若給出相對路徑及文件前綴,則到指定位置尋找。
②.能夠加載各類各樣的文件:.js、.vue、.less等等。
③.能夠省略掉from直接引入。
3.關於export
①.導出的能夠是對象,表達式,函數,類
②.導出是爲了讓別人導入
4.言外話:使用es6的話,有一個特別好的規範去遵照,airbnb的es6規範(https://github.com/airbnb/javascript)
複製代碼

CommonJS:nodejs中使用較多,關鍵詞是require,沒寫過node包,只引用過別人的模塊,因此內部實現原理不是很清楚。

3.MVVM原理

MVVM是一種軟件架構模式,MVVM有助於先後端分離。 View:視圖層,粗略理解爲DOM。 Model:與數據庫對應的model,通常爲json格式,做爲req的body經過http(s)與數據庫實現通訊。 ViewModel:View與Model經過ViewModel實現雙向綁定。

核心是提供對View和ViewModel的雙向數據綁定,這樣使得ViewModel的改變View當即變化,MVVM在前端的實現有:angular,vue,react。

vue中的經常使用數據雙向綁定。

view:{{message}}
viewModel v-model="message"
model:message
複製代碼
<div id="app-6">
  <p>{{ message }}</p>
  <input v-model="message">
</div>

var app6 = new Vue({
  el: '#app-6',
  data: {
         message: 'Hello Vue!'
  }
})
複製代碼

單文件組件中的話,就多了一個用html5的template標籤將view和viewModel包裹起來,model部分停留在script標籤部分。

<template>
     view
     viewModel
</tamplate>
<script>
     model
</script>
<styles>
     爲了讓view好看點
</styles>
複製代碼

react的話,我在使用的過程當中,沒有據說過雙向綁定的東西,對redux reducers推薦寫爲純函數印象深入,純函數的話,感受應該有點單項數據流的意思。

既然說到框架了,說一個最讓我感受有趣的點,那就是組件間的通訊,對於簡單組件,只涉及父子級別的通訊的,vue使用on emit的方式,react使用props。對於複雜級別通訊,爺爺父親兒子孫子等等時,vue推薦使用vuex,react推薦使用redux,統一的全局狀態樹用來作狀態管理很是好,可使得邏輯很是清晰。vue項目文件結構研究不深,react的項目文件結構的話,presentational和containers的設計方法感受很是有道理,一個負責視圖一個負責數據,很是清爽。

4.最熟悉的框架路由機制

vue路由依賴:vue-router 經過組合組件來組成單頁應用程序,只須要將組件映射到路由便可。 前端路由的核心,就在於 —— 改變視圖的同時不會向後端發出請求。 須要注意2種模式的區別:hash模式和history模式,hash模式會在後面加一個很醜的#,能夠開啓history去掉。 hash模式原理:它的特色在於:hash 雖然出如今 URL 中,但不會被包括在 HTTP 請求中,對後端徹底沒有影響,所以改變 hash 不會從新加載頁面。hash能夠理解爲錨點,例如./index.html/#/foo,hash值爲#/foo,這樣不會跳轉頁面。就至關於統一頁面的不一樣錨點,頁面間跳轉與 ./index.html/#foo到./index.html/#bar相似。

./store/index.js

import Router from 'vue-router'
Vue.use(Router)
export default new Router({
  routes: [
  {
  path: '/common',
  name: 'common',
  component: Common
  }
]

複製代碼

路由層面還會包括嵌套路由,動態路由以及重定向,至關於本身模仿瀏覽器請求而後服務器響應模式,其實不涉及向後端請求,僅在瀏覽器就能夠實現頁面跳轉,前段時間我作的用戶權限控制就用到了vue-router,相比MVC結構下的後端路由,清晰了很多,這樣後端只要負責路由編寫api就好。

5.狀態管理

下面是我在用vuex作項目時的一些思考,簡單修改了一下,也添加了一些關於redux的思考。

vuex state,前端data view,前端DOM actions,用戶操做,引發data變化從而致使DOM變化。

多個組件(視圖)共享狀態:通俗來說,就是多個組件間會通訊時,致使從後端拿來的數據發生變化,當組件較多時,若是兄弟組件間的通訊都依賴父組件進行通訊,會致使組件間的耦合很是高,從而致使項目邏輯混亂,難以維護。

多個組件(視圖)依賴於同一狀態。 來自不一樣視圖的行爲須要變動同一狀態。

全局單例模式管理,把組件的共享狀態抽取出來 無論在組件樹的哪一個位置,任何組件都能獲取狀態或者觸發行爲!

實踐出真知:

1.state存放在index.js中,建立的Store實例getter,mutations,actions等,能夠分離出來
2.getters存放在getter.js中,數據流爲state→getter→組件,getter至關於一個數據獲取過濾器,從倉庫拿特定數據到組件,至關於對computed的集中處理。
3.mutations存放在mutations.js中,數據流爲組件→mutations→state,mutations至關於一個數據提交發射器,從組件提交數據到倉庫
4.actions存放在actions.js中,數據流爲組件→actions→mutations→state,異步操做的主要場所。
5.modules是開發大型應用時須要用到的,每一個module都有單獨的states,getters,actions以及mutation,有一股nodejs模塊的味道。
複製代碼

vuex三原則:

1.惟一數據源
2.保持狀態只讀
3.數據改變只能經過純函數完成 更改 Vuex 的 store 中的狀態的惟一方法是提交 mutation。
複製代碼

必定要注意mutation和action的區別!

mutation只變動本地的狀態,也就是說,直接只去修改store中的數據。 action包含異步操做,直接調用api,經過api的數據,再提交mutation。

能夠說,action只比mutation多了一個異步調用api的操做,由於調用api後,通常有2種返回結果,succes或者error,或者是promise的多種狀態,根據不一樣的。

最近在學習redux,組件dispatch一個action到store,至關於發送一個http請求,而後store作出響應,返回一個response給組件。和vuex大體相似,惟一有區別的是,vuex還須要引入react-redux,引入Provider和connect鏈接組件和store。

6.統計字符串中單詞出現次數

" hi how are you i am fine thank you youtube am am ",統計"you"出現的次數。

function wordCount(str,word){
  var str = str || "";
  var word = word || "";
  var strArr = str.split(" ");
  var count = 0;
  for(var i=0;i<strArr.length;i++){
      if(word===strArr[i]){
          count++
      }
  }
  return count;
}
wordCount("hi how are you i am fine thank you youtube am am","you");
複製代碼

若是字符串沒有空格怎麼辦?

function wordCount(str,word){
  var str = str || "";
  var word = word || "";
  var count = 0;
  var index = str.indexOf(word);
  while(index!==-1){
      count++;
      str = str.substr(index+word.length);
      index = str.indexOf(word)
  }
  return count;
}
wordCount("hihowareyouiamfinethankyouyoutubeamam","you");
複製代碼

若是不用js內置字符串函數,本身用每一個字符對比呢?

function wordCount(str,word){
  var num = 0;
  var str = str+" " || "";
  var word = word || "";
  var strArr = str.split("");
  var wordArr = word.split("");
  var count = 0;
  function compare(arr1,a,arr2,b){
        if(b+a<arr2.length){
          if(arr1[a]===arr2[b+a]){
            num++;
            return compare(arr1,a+1,arr2,b+1)
          }
          if(num===arr1.length){
            count++
            num = 0;
          }
        }
  }
  for(var i=0;i<strArr.length;i++){
      for(var j=0;j<wordArr.length;j++){
        if(wordArr[wordArr.length-1]===strArr[i+wordArr.length-1]){
          compare(wordArr,0,strArr,i+0)
        }
      }
  }
  return count;
}
wordCount("hihowareyouiamfinethankyouyoutubeamam","am");
複製代碼

能夠更加高效一些嗎?

function wordCount (str,word) {

  var str = str+" " || "";
  var word = word || "";
  var strArr = str.split("");
  var wordArr = word.split("");
  var wordArrLen = wordArr.length;
  var count = 0;
  var num = 0;

  function compare (arr1,a,arr2,b) {
        if(b+a<arr2.length){
          if(arr1[a]===arr2[b+a]){
            num++;
            return compare(arr1,a+1,arr2,b+1)
          }
          if(num===arr1.length){
            count++;
            num = 0;
          }
        }
  }

  var j = 0;
  while(j<wordArrLen){
      var i = 0;
      while(i<strArr.length){
          if(wordArr[wordArrLen -1]===strArr[i+wordArrLen -1]){
            compare(wordArr,0,strArr,i+0);
          }
          i++;
      }
      j++;
  }
  return count;
}

wordCount("hihowareyouiamfinethankyouyoutubeamam","a");

//1.調整最高層級遍歷數組,從37的2次方降到3的2次方,從1369降到9
//2.合併控制變量和控制條件,使用while替代for,去除JS引擎查詢i,j是否存在的消耗,會稍微下降代碼可讀性
//3.對重複引用的wordArr.length,賦值給局部變量wordArrLen,在這裏,Array.prototype.length的查詢次數從3次下降到1次
複製代碼

面試2 - offer2 莫愁前路無知己,天下誰人不識君

我原本就不想再繼續找了,可是今天朋友給我一個建議,跳槽前多投幾家,說不定能夠找到更好的,而後我就想到 V 站上看到好多求職貼,因此就索性再試試看有沒有更好的坑。

簡歷: 前端開發-簡書-趁你還年輕233

簡書 : 趁你還年輕233

github: FrankKai

segmentFault:趁你還年輕

座標:杭州

而後我在V站上發了貼,頗有緣分,一個V友加了個人好友,約好時間進行了一次電話面試,後面瞭解好公司技術氛圍和商議好薪資待遇後,成功拿到了offer,薪資待遇和第一家差很少,這家是浙大系的公司。

我和麪試官很聊得來,最後甚至都聊到了吃雞,因爲電話面試太愉快了,因此此次電話面試到如今我僅記得一道跨域題了。第三家公司面試官也很贊,天氣寒冷,友情提醒我注意路上冰凍,不過因爲第三家面試在明天晚上才進行,因此我把第三家的BOSS直聘題也總結在一塊兒了:一些特別棒的面試題[1]

貼一下面試題和個人回答。

1.平時有遇到過跨域問題嗎?
2.下面這段代碼最終輸出什麼?
3.["1","2","3"].map(parseInt)返回的是什麼?
4.下面代碼中「入庫」的顏色是?
複製代碼

1.平時有遇到過跨域問題嗎?

說到跨域問題,就必定要說到同源,什麼是同源,相同協議,相同域名,相同端口,即爲同源。

不一樣源之間的通訊就會有跨域問題,通常來講是客戶端訪問服務器,服務器上去配置跨域。 我遇到的跨域問題都是後端去配置一下就能夠解決的,好比我前端在用vue的官方推薦異步請求庫axios,去請求後端的koa開啓的後端服務時,就會遇到跨域的問題,例如koa使用依賴koa-cors就能夠,具體的話,就是Access-Control-Allow-Origin: 源名,能夠爲*或者是特殊的源。或者是傳統的maven或者nginx上,也能夠很方便的配置跨域。

JSONP有用過嗎?JSONP沒用過,可是原理貌似是經過js加載一個script DOM標籤進來,而後在新的script的src中引入想要執行的代碼。 其實跨域問題在後端中也有相似的,只不過是叫作進程間通訊,有IPC,RPC等等方式進行進程間通訊。

2.下面這段代碼最終輸出什麼?

let O = function(name){
 this.name = name || 'world';
};
O.prototype.hello = function(){
 return function(){
  console.log('hello ' + this.name);
 };
};
let o = new O;
let hello = o.hello();
hello();
複製代碼

年輕的個人答案是:hello world。

答案顯然是不對的,由於這是一道陷阱題,陷阱就在於O.prototype.hello調用後,return的是一個函數,這麼作的話,在執行新實例o的hello方法是,this其實已經變成了window。

那麼答案是hello undefined嗎?

年輕的你又錯了,並非。

而是 hello 。

請注意,是hello ,而不是hello undefined,而是空字符串

緣由就在於window.name是事先是有定義的,並且其值爲空。

不信的話你能夠在控制檯打印window.name,返回的是"",你再打印window.yourname試試看,好比window.frank,返回的就是undefined了。

感謝@ygh1的提醒,打印結果和運行環境也是有關的,由於node中全局是global,browser中全局是window。

剛在node裏跑了下有陷阱的題目,打印出來確實是hello undefined,由於node中的global對象沒有初始的name屬性。

因此最正確的答案應該是:

node環境:hello undefined
browser環境:hello _____(非零寬空字符)
複製代碼

而我在工做中,遇到的更多的常見的像上面同樣的工廠函數式的寫法是這樣的。

let O = function(name){
 this.name = name || 'world';
};
O.prototype.hello = function(){
  console.log('hello ' + this.name);
};
let o = new O("frank");
let hello = o.hello("frank");
複製代碼

打印結果爲:hello frank。

若是不傳入frank的話,打印出的是默認值hello world。

3.["1","2","3"].map(parseInt)返回的是什麼?

A. [1,2,3] B.["1","2","3"] C.[1,1,1] D.其餘

這特麼又是一道陷阱題,還好我以前在看MDN的map函數時,看到過這個陷阱。

正確答案是D:其餘。

其餘的具體值爲多少?[1,NaN,NaN]。

不敢相信吧,爲何不是可愛的[1,2,3]呢?

由於map的callback有3個參數,currentValue,index和array,parseInt有2個參數,string和radix(進制),只傳入parseInt到map中的話,會自動忽略第三個參數array,可是不會忽略index,因此就會把0,1,2做爲第二個參數傳給parseInt。

若是還不明白的話,咱們把["1","2","3"].map(parseInt)的每一步都拆開來。

parseInt("1",0) 此時將字符"1"轉換爲O進制數,因爲0進制數不存在,因此返回Number類型的1。
parseInt("2",1) 此時將字符"2"轉換爲1進制數,因爲超出進制數1,因此返回NaN。
parseInt("3",2) 此時將字符"3"轉換爲2進制數,因爲超出進制數2,因此返回NaN。
複製代碼

至此,真相大白。 那麼經常使用的非陷阱式map寫法是怎樣的呢?

像這樣:["1","2","3"].map(x=>parseInt(x))

傳一個完整的函數進去,有形參,有callback,這樣就不會形成由於參數傳入錯誤而形成結果錯誤了,最後返回一個漂漂亮亮的經由純函數處理後的新數組回來。

其實這裏若是再深刻的話,能夠再考察純函數是什麼?

純函數其實就是一個不改變輸入,可是能夠藉助輸入,產生一個以輸入爲原材料,通過加工處理後,輸出一個全新的輸出的函數,關鍵在於不改變輸入,純函數是編寫redux的reducer必須具有的技能點。

剛纔公司的大牛過來,說他歷來不用parseInt,他用加號,+"1" 返回1,+"2"返回2。大牛果真大牛,黑科技是真的多。

4.下面代碼中「入庫」的顏色是?

<ul class="list" id="list">
 <li class="favorite">
  <span>出庫</span>
 </li>
 <li class="favorite">
  <span class="highlight">入庫</span>
 </li>
</ul>
<style>
#list .favorite:not(#list) .highlight{
 color: red;
}
#list .highlight:nth-of-type(1):nth-last-of-type(1){
 color: blue;
}
</style>
複製代碼

A. red B.blue C.black

個人答案是:我猜一下,多是A,由於A的權重是最大的,僞類選擇器的權值應該比較小吧。

面試官發來一個👍,明天能夠來公司面談嗎?已經約好明天面試。

這道題的解答到此爲止,由於我是真的真的對CSS不感興趣,各位看官老爺請原諒我。

面試-3 未經過

1.說下下面兩種font-size單位的異同?

em rem

兩者的爲了保證用戶修改字體大小時,保持垂直方向上的字體大小一致。與px不一樣,兩者都是字體計算大小單位,也就是說,須要經過計算得出其大小,轉換成px,微信小程序的rpx也是這樣,最後仍是轉換成了px,多是借鑑了rem的思想吧。

可是em相對於繼承來的父元素,rem相對於根元素。聽大牛說,rem在國內使用比較多,可能侍使用習慣問題。我本身也以爲rem使用起來更簡單,爲根元素的font-size賦一個初始值,再配合css的媒體查詢,能夠動態的改變這個全局的單位,能夠說是牽一髮而動全身,使用起來很是方便,而em的可閱讀性就不好了,有的時候爲了算字體大小,須要一級一級找上去,很是不直觀。

現代的經常使用的瀏覽器,1rem等於16px,可是能夠經過html{font-size:percentage/num }來控制。

舉2個 rem和em例子對比下。

html簡寫結構:

<html>
    <body>
        <div></div>
    </body>
</html>
複製代碼

rem 例子:

html { font-size:62.5%; }  /* =10px */
body { font-size: 2.0rem; } /* =20px */
div   { font-size: 1.0rem; } /* =10px */
複製代碼

em 例子:

html { font-size:62.5%; }  /* =10px */
body { font-size: 2.0em; } /* =20px */
div   { font-size: 1.0em; } /* =20px */
複製代碼

MDN的font-size章節給出了em和rem的很是好的解釋,英文原版很是直觀,我這裏再貼一下:

em

Represents the calculated font-size of the element. If used on the font-size property itself, it represents the inherited font-size of the element.

rem

Represents the font-size of the root element (typically ). When used within the root element font-size, it represents its initial value (a common browser default is 16px, but user-defined preferences may modify this).

其實em和rem與MVVM框架的組件間通訊有些相似,都有逐級繼承和全局影響的概念。em是逐級傳遞的,也就是繼承,框架中用props和事件訂閱發佈的方式也是這樣,爺,父,孫的傳遞都是要一級一級去傳遞的,爺爺想直接傳授點技能給孫子必須先傳授給父親,爺爺→父親→孫子;而rem就和框架中的狀態管理庫很像,例如vuex和redux,抽取出一個全局的狀態樹,不用一級一級的去很複雜的去繼承,爺爺想教教孫子,直接就能夠傳授給孫子,爺爺→孫子

2.只用一個div 實現定時紅綠燈

default

<!DOCTYPE html>
<html lang="zh-cn">
    <head>
        <meta charset="utf-8" />
        <title>僅用一個DIV實現紅綠燈</title>
        <style>
        	@keyframes light{
        		0%{
        			background-color: green;
        			left: 0;
        		}
        		33.3%{
        			background-color: green;
        			left: 0;
        		}
        		33.4%{
        			background-color: yellow;
        			left: 200px;
        		}
        		66.6%{
        			background-color: yellow;
        			left: 200px;
        		}
        		66.7%{
        			background-color: red;
        			left: 400px;
        		}
        		99.9%{
	       			background-color: red;
        			left: 400px;
        		}
        	}
        	.traffic-light{
        		position: relative;
        		width: 200px;
        		height: 200px;
        		border-radius: 50%;
        		animation: light 3s ease-in-out 0s infinite;
        	}
        	.container{
        		width: 600px;
        		border:10px solid #000;
        		border-radius: 20% 20%;
        	}
        </style>
    </head>
    <body>
    	<div class="container">
    		<div class="traffic-light"></div>
    	</div>
    </body>
</html>
複製代碼

面試-4 未經過

因爲種種緣由,開始了新一輪的面試,這一輪面試可謂收穫頗豐。 與各類各樣的面試官交流下來,除了收穫到一些疏漏的知識點外,發現面試其實很是考驗面試官的水平。揣摩出一些如何成爲一名合格的前端面試官方法。

以及很重要的老哥的經驗:進大廠前必需要作的準備,提早一個月刷題。

1.setTimeout與函數調用棧

console.log(1);
setTimeout(function(){
    console.log(2);
},0);
console.log(3);
複製代碼

輸出:1 3 2 緣由:Call Stack會最後調用setTimeout的callback,setTimeout中的callback是一個異步函數。 函數調用棧的部分能夠參考這裏:blog.risingstack.com/node-js-at-…

2.function foo 與 var foo的提高優先級

console.log(typeof foo);
var foo = "foo";
function foo(){}
複製代碼

輸出:function

console.log(typeof foo);
function foo(){}
var foo = "foo";
複製代碼

輸出:function

function優先級比var高,不管在其先後,都會覆蓋掉同名的var聲明。

3.let 塊做用域 與 setTimeout

for(let i=0;i<6;i++){
    setTimeout(function(){
        console.log(i)
    },0)
}
console.log(i)
複製代碼

輸出:

0
Uncaught ReferenceError: i is not defined
1
2
3
4
5
複製代碼
  • Uncaught ReferenceError: i is not defined 因而可知for語句的塊做用域,不只僅在花括號中生效,在圓括號中也生效。
  • 輸出0 1 2 3 4 5 的緣由 setTimeout的callback是異步函數,for循環實質上是在作異步循環隊列,setTimeout的callback會被調用5次,因爲let會爲每次的i分配獨立的地址空間,所以每一次傳不一樣的值進去。

爲何在debug的過程當中,打印順序是混亂的? (等把規範的timers章節翻譯完,再來解決) breakpoint打在console.log(i)上。

Uncaught ReferenceError: i is not defined
0 
2
5
4
3
1
複製代碼

若是將let替換成var呢?

for(var i=0;i<6;i++){
    setTimeout(function(){
        console.log(i)
    },0)
}
console.log(i)
複製代碼

輸出: 6個6 緣由:

  • 打印的是window.i 每一個傳入的i指向相同的i,傳入時依次window.i的值爲1,2,3,4,5,6,可是都是同一個引用,當函數調用棧開始執行setTimeout的callback時,window.i已經變爲了6
  • var 不會限制塊做用域 不會分配6個獨立的地址空間給setTimeout的callback

4.爲何Object.toString.call([1,2,3])返回[object Array]?[].toString()能夠返回[object Array]嗎?

若想回答這個問題,須要深刻理解Object.prototype.toString.call()

難道真的像本身理解的那樣,是經過call將[1,2,3]做爲Object.toString的實參傳遞了進去嗎?不是。 直接Object.toString([1,2,3])不能實現一樣的功能嗎?不能。 而實際上也有Array.proto.toString()這種形式,因此是能夠直接調用arr.toString()的,這樣能檢測出嗎?不行。

那究竟是什麼緣由? 先來肝一個表格。


數據類型 例子 return
字符串 "foo".toString() "foo"
數字 1.toString() Uncaught SyntaxError: Invalid or unexpected token
布爾值 false.toString() "false"
undefined undefined.toString() Uncaught TypeError: Cannot read property 'toString' of undefined
null null.toString() Uncaught TypeError: Cannot read property 'toString' of null
String String.toString() "function String() { [native code] }"
Number Number.toString() "function Number() { [native code] }"
Boolean Boolean.toString() "function Boolean() { [native code] }"
Array Array.toString() "function Array() { [native code] }"
Function Function.toString() "function Function() { [native code] }"
Date Date.toString() "function Date() { [native code] }"
RegExp RegExp.toString() "function RegExp() { [native code] }"
Error Error.toString() "function Error() { [native code] }"
Promise Promise.toString() "function Promise() { [native code] }"
Obejct Object.toString() "function Object() { [native code] }"
Math Math.toString() "[object Math]"

爲何會出現下面的狀況?

Object.toString.call(Array)//"function Array() { [native code] }"
Object.prototype.toString.call(Array)//"[object Function]"
複製代碼

答案在這裏!

Object.toString()//"function Object() { [native code] }"
Object.prototype.toString()//"[object Object]"
複製代碼

Object對象和它的原型鏈上各自有一個toString()方法,第一個返回的是一個函數,第二個返回的是值類型。

既然知道了不一樣,如今咱們再來分析下Object.prototype.toString.call(Array)//"[object Function]"。 Array對象自己返回一個構造函數,Array//ƒ Array() { [native code] },而Object.prototype.toString()返回的是//"[object Type]"的形式,經過call將Array的this上下文切換到Object,從而調用了Object.prototype.toString(),所以返回[object Function]

須要注意的是:Math.toString()直接返回"[object Math]"。

實際開發中,咱們用到最多的多是:Object.prototype.toString.call([1,2,3])//"[object Array]"這種。

總結:

  • 通常狀況下,js中對象的toString(),返回字符串,內容與函數聲明語法有關,例如[1,2,3].toString()//"1,2,3"
  • 大多數都返回函數的完整源碼,Array.toString()//"function Array() { [native code] }"
  • 內置函數每每返回一個相似"[native code]"的函數體,須要配合call方法,好比Object.prototype.toString.call([1,2,3])//"[object Array]"

那麼不能夠直接Array.prototype.toString.call([1,3,4])嗎? 不行! 由於Array,Function,Date雖然是基於Object進行建立的,可是他們繼承的是Object.toString(),而不是Object.prototype.toString()。 再加深一遍印象:

Object.toString()//"function Object() { [native code] }"
Object.prototype.toString()//"[object Object]"
複製代碼

因此這就是必須用Object.prototype.toString()去檢測類型的緣由。

至於Object.prototype.toString()內部是怎麼實現的,等到時機成熟再去深刻。

5.綜合考察bind,call和apply的面試題

var obj = {
    a: 1,
    name: 'world',
    objSayName: function (fn) {
    	fn();
    }
}
function sayName () {
	return console.log(this.name);
}
obj.objSayName(sayName);
// 輸出:undefined
複製代碼

爲何? 在obj的objSayName內部,沒有修改this指向到當前調用對象。

題目一:對象內部方法,調用全局的函數 適用:多個對象(局部方法)複用同一全局函數 精簡:局部(方法)複用全局函數 方法:修改this指向,經過Function.prototype.bind()去顯式修改this指向到當前調用對象。 緣由:Calling f.bind(someObject) creates a new function with the same body and scope as f, but where this occurs in the original function,in the new function it is permanently bound to the first argument of bind, regardless of how the function is being used.bind only works once!

var obj = {
    name: '1',
    objSayName: function (f) {
      var g = f.bind(this);
	  console.log(g());
    }
};
function sayName(){
    return this.name;
}
obj.objSayName(sayName);

複製代碼

輸出:'1'

拓展: 題目二:若是全局方法想輸出對象的局部屬性,該怎麼辦? 適用:同一全局函數輸出多個對象(內部變量) 精簡:全局函數輸出局部(變量) 方法:使用apply或者call修改this指向到被調用對象 緣由:An object can be passed as the first argument to call or apply and this will be bound to it.

var obj = {
    name: '1',
    say: function (fn) {
        fn();
    }
};
function sayName(){
    return this.name;
}
sayName.apply(obj);
sayName.call(obj);
// 輸出:'1'
複製代碼

參考:developer.mozilla.org/en-US/docs/…

面試-5 offer 3 整個江湖都任我闖,個人生命像一首歌

現東家的面試題,是我最欣賞的一套面試題,在這裏已經工做了接近1年時間,成長許多。

題目主要分爲4個部分:

  • HTML
  • CSS
  • JS
  • 代碼

答案未驗證準確性,有待驗證並更新。 我將按照「1 year before」和「today」的角度去進行解答,也是對本身成長的一個記錄。

HTML

1.請描述cookies, sessionStorage和localStorage的區別

1 year before: cookies,須要與後端協做,一種認證方式,expires失效時間 sessionStorage,當前會話有效 localStorage,本地緩存,expires失效時間 today:

cookies
  • 一個HTTP cookie(web cookiebrowser cookie)是服務器發送給用戶web瀏覽器的一小段數據段。
  • 瀏覽器能夠把它存在本身本地,而且將它在下一個請求中發送給它的數據源服務器。
  • 典型的應用場景就是去判斷兩個請求是否來自同一個服務器----來自同一個登陸用戶,它是對無狀態的HTTP協議的一種有狀態記憶。
sessionStorage
  • key/value的方式存儲,會話存儲
  • 爲每個給定的origin維護一個分離的storage區域,在頁面會話期間可用
localStorage
  • key/value的方式存儲,持久化存儲
  • 瀏覽器關閉後從新打開,localStorage的鍵值對仍然存在

2.請解釋<script><script async><script defer>區別

1 year before: 常見的同步;異步;延遲加載。

today:

  • <script async>控制瀏覽器同異步加載腳本。若設置async爲false,那麼瀏覽器在HTML解析期間同步加載腳本。通常來講經過代碼document.creatElement()插入腳本是異步的,設置async爲false能夠將其控制爲同步。
  • <script defer>defer屬性用來控制script是否在HTML完成解析以後再執行,可是會在DOMContentLoad燃燒以前完成。

拓展: 1.什麼是DOMContentLoaded事件? DOMContentLoaded事件,會在初始化HTML document完成加載和解析觸發,無需等待stylesheets,images,以及字frame結束加載。Load事件和DOMContentLoaded事件很相似,常常有人混淆2個事件。 2.什麼是Load事件? load事件,會在完成一次徹底加載以後再觸發。 3.如何解決同步js阻塞DOM渲染的問題,最快速度渲染DOM? 異步化js優化stylesheets加載。 4.如何檢查document是否完成加載? document.readyState

  • loading 加載中。
  • interactive document完成加載,document已經被解析可是子資源例如images、stylesheets和frame賑災加載。
  • complete document以及子資源都已加載完成,此時會觸發load事件。

因此一次加載文檔資源的狀態有3個,loading``interactivecomplete

3.爲何一般推薦將CSS 放置在<head></head>之間,而將js<script></script>放置在</body>以前?

1 year before: 防止阻塞瀏覽器渲染,先執行CSSOM,再繪製DOM,再操做DOM。主線程單線程渲染UI。

today 從技術實現的角度講,先加載stylesheets而且繪製,DOM渲染結束後再加載並執行可能涉及DOM操做的js文件,避免js的執行致使渲染阻塞。 從用戶體驗的角度講,優先加載樣式表減小用戶面對空白網頁的時間,提高用戶體驗。

CSS

1.CSS中類(classes)和ID的區別

1 year before ①ID優先級高 ②ID惟一標識,不能重複

today ①語法不一樣,#idname, .classname ②影響元素不一樣,#idname做用單個元素,.classname做用全部元素 ③選擇器權重不一樣,#idname權值高於.classname

2.有哪些隱藏DOM的方法

1 year before

  • display: none
  • position: top right bottom left
  • transform
  • z-index
  • 移除DOM節點(JS)

today [譯]如何隱藏DOM元素?

3.請解釋*{ box-sizing: border-box }的做用,而且說明使用它有什麼好處?

1 year before 怪異盒模型。 計算方便,width包含了border,響應式百分比佈局。

today box-sizing的值有2種,一個是content-box,一個是border-box,content-box僅僅包含content。 border-box的width會將content, padding和border包含在內,例如width:100%指的是包含了content,padding和border的寬度,佈局時更好控制。

例如子元素繼承了父元素的width:100%,此時設置了子元素padding,border,若子元素的box-sizing是content-box,會致使溢出,而border-box的話,width:100%會很舒服地包含了padding和border。

由於這樣的應用場景不少,因此索性就爲全部標籤都設置成border-box,有特殊狀況的再手動設置成content-box。

image

有一篇牆推IE怪異盒模型的文章:把全部元素的box-sizing都設置成border-box吧!

4.請問在肯定樣式的過程當中優先級是如何決定的(請舉例)?如何使用此係統?

1 year before

  • style屬性 <div style=""></div>
  • id
  • 標籤名
  • class
  • 僞類

每一個選擇器都有權值,權重爲和,#foo>.class::before 三者和爲權重,權值id>標籤>class>僞類。

today 優先級由高到低

  • !important 不建議的實踐
  • 行內樣式 <span style=""></span>
  • ID選擇器 #foo
  • 類選擇器.foo,屬性選擇器[type="radio"],僞類:hover
  • 類型選擇器p,span,僞元素::before

一個很優秀的說明css選擇器優先級的圖:specifishity.com/

image

通用選擇器(*),組合符(+,>,〜,'',||)和否認僞類(:not())對權重沒有影響。

5.請問爲什麼要使用translate()而非absolute positioning,或反之的理由?爲何?

1 year before absolute

  • 從正常文檔流移除
  • 不佔據頁面佈局空間
  • 開闢新的stacking context
  • 影響其餘佈局元素
  • 消除邊緣重疊

減小了計算,translate()不影響其餘元素,性能更好,GPU計算次數更少

today 在個人這篇博問中有答案:CSS3動畫卡頓性能優化解決方案

translate()涉及到的是合成器線程,與主線程是相互獨立的,因此會比較快。 而absolute positioning涉及到的是主線程,會致使主線程負責的佈局重繪和js執行,因此會比較慢。

JS

1..call和.apply的區別是什麼?

1 year before

  • 傳入參數方式不一樣,但都是動態修改this上下文
  • call 會有函數執行棧的操做
  • apply僅僅將arguments傳到新的類中

today 關於這個問題曾經產出2篇博客: 從規範去看Function.prototype.apply究竟是怎麼工做的? 從規範去看Function.prototype.call究竟是怎麼工做的? call是索取,apply是付出。 從call和apply的字面意思就能夠看出,call調用,apply應用,調用函數,應用參數。 call和apply的主要區別在於,call僅僅切換this上下文到其餘類,從而調用本身不存在的方法;而apply主要是爲了將其餘類型的參數傳遞到本身內部,再調用本身的方法。

假設有foo,bar。 foo.call(bar) bar調用foo的方法,實例Object.toString([1,2,3])->"[object Array]",數組實例調用了Object類的toString方法。 foo.apply(null, bar) foo的方法應用bar的參數,Math.max.apply(null, [1,2,3])->3,Math的max方法應用了[1,2,3]中的每一個參數。

2.請解釋JSONP的工做原理,以及它爲何不是真正的Ajax?

1 year before JSONP 原理:異步插入一個<script></script>,會有XSS問題 緣由:沒有調用XMR對象 today 一種比較古老的不安全的跨域請求訪問方式,沒有調用XMR對象,服務器容許瀏覽器在query parameter中傳遞瀏覽器內定義的函數,而這個函數是有機率被XSS攻擊改寫的。

來自StackOverflow高票答案:stackoverflow.com/questions/2…

JSONP不是一個很複雜的問題。 假設咱們在example.com域名下,此時咱們想給example.net域名發送一個請求。爲了請求成功,須要跨越域名邊界,這對於瀏覽器來講是禁忌。

繞開這個限制的一種方式是<script>標籤。當你使用script標籤的時候,域名限制會被忽略,可是對結果不能作任何處理,腳本是被評估過的。

開始進入JSONP。當你發送一個請求到支持JSONP的服務器,你會傳一些特殊的關於你的頁面的數據給服務器。這種方式下,服務器會以你的瀏覽器處理起來方便的方式包裝響應。

例如,服務器須要一個叫作callback的參數去開啓JSONP功能。而後你的請求會想下面這樣: http://www.example.net/sample.aspx?callback=mycallback

沒有JSONP的狀況下,這能夠返回一些基本的JS對象,例如: {foo: 'bar'}

然而,在支持JSONP的狀況下,服務器接收到callback參數,它包裹結果的方式是不同的,會返回下面這樣的數據: mycallback({foo: 'bar'});

就如你縮減,他會調用瀏覽器端的方法。因此,在你的頁面上callback的定義以下:

mycallback = function(data){
  alert(data.foo);
};
複製代碼

如今的話,在腳本加載成功後,它會被評估,而後函數執行。cross-domain請求成功!

因此JSONP存在一個很嚴重的問題:你失去了對請求的控制。例如,沒法得知錯誤代碼的返回。可使用定時器去監控請求,可是這不是很好。JSONRequest是一個很是好的跨域腳本執行的方式,安全,而且得到更多對請求的控制。

2015年,CORS是一個與JSONRequest能夠抗衡的方案。JSONP在老式瀏覽器下仍舊有用,可是不安全。 CORS是作跨域請求訪問的更安全、更高效的一種方式。

3.用過javascript模板系統嗎?都使用過哪些庫?

1 year before jade vue angular react { ... }或者{{ ... }}

today: 一些好用的模板引擎庫

經常使用的仍是前端框架自帶的以及pug,因爲我只對vue.js的比較熟悉因此就沒有羅列react和angular的demo。

4.== 和 === 有什麼不一樣?

1 year before 這個問題寫過博客,看過規範。 ①===是==的子集 ②==有類型轉換 ③規範內實現機制不一樣 today 你真的理解==和===的區別嗎?

5.請解釋Javascript的同源策略(same-origin policy)

1 year before 瀏覽器安全機制

  • same-origin:相同協議,相同host,相同端口
  • 跨域問題:CORS 能夠後端設置容許 cross-origin-access信息

today 如何理解same-origin policy?

6.你使用過Promises及其polyfills嗎?請寫出Promise的基本用法(ES6)

1 year before axios

  • axios get() post()
  • 前端請求、響應攔截器

today

  • Promise.all() 只有當全部的異步Promise執行完爲resolved狀態時,返回一個Promise
  • Promise.prototype.catch() 捕捉Promise執行過程當中捕捉到的異常
  • Promise.prototype.finally() 是catch和then的並集,經常使用於在catch和then中都運行的代碼,避免重複
  • Promise.prototype.then() Promise執行完畢,進行下一步
  • Promise.race() Promise競爭,返回Promise集合中最早resolve或者reject出來的Promise;經常使用於時間控制、停止Promise 能夠參考我發的一篇帖子:什麼狀況下會用 Promise.race()?
  • Promise.reject() Promise類捕捉異常
  • Promise.resolve() Promise類解析數據

7.使用Promises而非回調(callbacks)優缺點是什麼?

1 year before 解決了callback hell問題。

today 以一個圖片資源加載繪製canvas。

class CanvasImage {
  constructor(url, width, height) {
    this.width = width || 500;
    this.height = height || 500;
    this.url = url || '';

    this.element = new Image(this.width, this.height);
  }
  get imageElement() {
    return this.element;
  }
}
複製代碼

callback hell方式

source.onload = function() {
  const target = new CanvasImage(url, 80, 80).imageElement;
  target.onload = function() {
    const main = new MainCanvas(source, target, 'right').canvasElement;
    context.drawImage(main, 0, 0, 500, 500);
  };
};
複製代碼

Promise方式

const sourcePromise = new Promise((resolve) => {
  setTimeout(() => {
    const target = new CanvasImage(url, 80, 80).imageElement;
    resolve(target);
  }, 0);
});
source.onload = function() {
  sourcePromise.then((target) => {
    const main = new MainCanvas(source, target, 'right').canvasElement;
    context.drawImage(main, 0, 0, 500, 500);
  });
};
複製代碼

async/await方式

function sourceCanvasImage() {
  return new Promise((resolve) => {
    setTimeout(() => {
      const target = new CanvasImage(url, 80, 80).imageElement;
      resolve(target);
    }, 0);
  });
}

async function mergeCanvas() {
  const targetElement = await sourceCanvasImage();
  const main = new MainCanvas(source, targetElement, 'right').canvasElement;
  context.drawImage(main, 0, 0, 500, 500);
}

source.onload = function() {
  mergeCanvas();
};
複製代碼

8.什麼是事件循環(event loop)?

1 year before

  • 異步原理
  • 事件訂閱、事件發佈
  • 異步非阻塞式事件

today 官方的解釋更加權威:nodejs.org/de/docs/gui…

什麼是Event Loop?event loop容許Node.js執行非阻塞的I/O操做-----儘管JS是單線程的-----它儘量地經過把操做卸載到系統內核(kernel)。

由於大多數現代的內核(kernel)是多線程的,它們能夠在後臺處理多個操做。當其中之一完成後,kernel會告訴Node.js一個適當的callback能夠被添加到poll queue(輪詢隊列)中而且執行。

更多原理上的內容,能夠參考:[譯]Node.js Event Loop,Timers和 process.nextTick()

event loop,原理細節包括如下內容

  • call stack
  • (macro)task queue
  • microTask queue
  • background thread

其中前三部分屬於main thread,能夠閱讀node源碼一探究竟。最後的background thread屬於libuv的部分,能夠去深刻libuv源碼(這是一個專門處理異步的c語言庫)理解其實現機制。

可是閱讀源碼須要很是好的基礎。這裏推薦一篇囊括了以上知識點的很是走心的文章:blog.risingstack.com/node-js-at-…

代碼

1.foo的值是什麼?

var foo = 10 + '20';

1 year before: 30

today: "1020"

2.如何實現如下函數?

add(2, 5);// 7
add(2)(5);// 7
複製代碼

1 year before 經過arguments類數組對象。

function foo(){
    var sum = 0;
    for(var i = 0; i<arguments.length; i++){
        sum += arguments[i]
    }
    if(arguments.length>=2){
        return sum;
    }else{
        return foo;
    }
}
複製代碼

add(2)(5)運行失敗。

today

const add = (a, b) => {
    const result =
      a && b
        ? a + b
        : function(b) {
            return a + b;
          };
    return result;
 };
複製代碼

3.下面兩個alert的結果是什麼?

var foo = "Hello";
(function() {
    var bar = " world";
    alert(foo + bar);
})();
alert(foo + bar);
複製代碼

1 year before "undefined World" "Hello undefined"

today "Hello world" // 當即執行函數做用域能夠訪問全局變量 Uncaught ReferenceError: bar is not defined // 全局做用域不能夠訪問局部變量

4.下面代碼的輸出是什麼?

console.log('one');
setTimeout(function() {
    console.log('two');
}, 0);
console.log('three');
複製代碼

1 year before one three two

today one three two

緣由:優先執行函數調用棧中任務,setTimeout排入宏任務隊列延後執行。 event loop包括call stack,(宏)任務隊列,微任務隊列和background thread,而call stack中的普通代碼優先執行,setTimeout會經由background thread進入宏任務隊列,宏任務隊列間隙執行微任務隊列。

image

5.下面代碼的輸出是什麼?

function getResult(value, time){
    return new Promise((resolve)=>{
        setTimeout(()=>{
            console.log(value);
            resolve();
        }, time);
    });
}
(async () => {
    const a = getResult(1, 300);
    const b = getResult(2, 200);

    await a;
    await b;
})();
(async () => {
    await getResult(1, 300);
    await getResult(2, 200);
})();
複製代碼

1 year before 1 2

today 2 1 1 2

這是一道考察async的題目:如何理解async函數?

6.下面的代碼輸出是什麼?

var obj = {
    a: 1,
    name: 'world',
    objSayName: function(fn) {
         fn();
    }
}
var name = 'hello';
var arr = [1, 2, 3, 4, 5];

function foo(o) {
    var bar = arr || [6, 7, 8];
    var arr = [4, 2, 9];
    var baz = o;
    baz.a = 2;
    console.log(bar, obj.a);
}

function sayName() {
    return console.log(this.name);
}

foo(obj);
obj.objSayName(sayName);
複製代碼

1 year later [4,2,9] 2 'hello'

today [6,7,8] 2 'hello'

緣由: 變量提高。

var bar,arr,baz;
bar = arr || [6, 7, 8];// 此時arr是undefined,所以bar獲得了[6, 7, 8]賦值
arr = [4, 2, 9];
複製代碼

baz得到了obj的引用,全部修改baz至關於修改obj,因此打印出2.

由於閉包,全局的sayName函數內的this指向全局,因此是hello。

我想成爲一個很厲害的人,讓這個世界由於有了我而有一點點不同,哪怕,只有一點點

貼一下本身理想中的團隊的關注點

1.我的前端技術的成長空間

好比資深前端對初級前端的指導,前端團隊成員間的學習和提高等等 這個最重要,個人目標是2年時間成爲基礎紮實,有獨立前端技術看法的開發者

2.公司對員工成長和進步的重視程度

例如新人培訓,技術分享,技術翻譯等等

3.公司加班狀況是996仍是10105或者是按照項目進度安排的

只要是一幫追求前端極致的人,996是徹底OK的

4.員工補貼,福利

例如過節補貼,工會福利

5.績效考覈和獎金

例如績效考覈,年終獎金

此次年後換工做我但願本身能在一家公司呆至少2年以上,因此這些方面我都須要瞭解清楚再作決定,須要慎重一些,但願可以加入一個有趣而且有實力的團隊~

簡歷戳這裏: 前端開發-簡書-趁你還年輕233

最後再說句體題外話,3家公司都在用vue,都問我有沒有用過vue...

That's it !

趁你還年輕

2018年1月31日

於凍成狗的冰雪杭州

如何成爲一名合格的面試官?

  • 學會傾聽 不管面試者有多少職場上的不如意想和你傾訴,都要耐心聽他講完,不要打斷他
  • 學會定位 根據面試者的工做經驗和工做場景,對能力進行簡單定位,雖然這偶爾會有所偏頗,可是對於後續提問會有很好的幫助
  • 學會理解 理解面試者想要表達的對知識點的理解,即便他講的很模糊,儘量捕捉其理解的部分
  • 學會引導 當面試者遇到一道棘手的題目時,若是對方邏輯不清楚,學會化繁爲簡,由淺入深去作引導;假設對方對當前的題目遊刃有餘,引導深刻原理或者是擴展出應用場景
  • 學會挖掘 學會挖掘出面試者身上的閃光點,聰明,執着,這些都是很是好的品質
  • 學會尊重 當面試者急於想得知面試官的評價時,不管你對他是否滿意,都採起"若是有新的進展,咱們後續會再通知你"的方式
  • 學會沉默 當面試者想得知你對問題的見解時,不要作太深層次的講解,點到爲止,由於有限的面試時間主要目的是爲了考察面試者的能力
相關文章
相關標籤/搜索