十道前端面試題第【02】篇

1、運行下面代碼,請依次寫出控制檯打印的順序。

console.log(1)
setTimeout(()=>console.log(2), 0)
new Promise((resolve,reject)=>{
  console.log(3)
  setTimeout(()=>resolve(4), 0)
}).then(res=>{
  console.log(res)
  console.log(5)
})
requestAnimationFrame(()=>console.log(6))
console.log(7)

答案:有可能是1 3 7 6 2 4 5,也有可能是1 3 7 2 4 5 6

2、封裝方法 arr2tree,把下面數組轉化成樹結構。

# 輸入:源數組
var arr = [
  { id: 0, name: '新聞' },
  { id: 1, name: '體育', pid: 0 },
  { id: 2, name: '籃球', pid: 1 },
  { id: 3, name: '足球', pid: 1 },
  { id: 4, name: 'NBA', pid: 2 },
  { id: 5, name: 'CBA', pid: 2 },
  { id: 6, name: '娛樂', pid: 0 },
  { id: 7, name: '小品', pid: 6 },
  { id: 8, name: '相聲', pid: 6 },
]
# 輸出:樹結構
var tree = [
  { 
    "id": 0, "name": "新聞", 
    "children": [
      { 
        "id": 1, "name": "體育", "pid": 0, 
        "children": [
          { 
            "id": 2, "name": "籃球", "pid": 1, 
            "children": [
              { "id": 4, "name": "NBA", "pid": 2 }, 
              { "id": 5, "name": "CBA", "pid": 2 }
            ] 
          }, 
          { "id": 3, "name": "足球", "pid": 1 }
        ] 
      }, 
      { 
        "id": 6, "name": "娛樂", "pid": 0, 
        "children": [
          { "id": 7, "name": "小品", "pid": 6 }, 
          { "id": 8, "name": "相聲", "pid": 6 }
        ] 
      }
    ] 
  }
]
# 參考答案
function arr2tree(sourceArr) {
  let obj = {}
  for (let i = 0; i < sourceArr.length; i++) {
    obj[sourceArr[i].id] = sourceArr[i]
  }
  const result = []
  sourceArr.forEach(node => {
    if (!obj[node.pid]) {
      result.push(node)
      return
    }
    obj[node.pid].children = obj[node.pid].children || []
    obj[node.pid].children.push(node)
  })
  return result
}


3、什麼是跨域?什麼是瀏覽器同源策略?有哪些常用的解決跨域方案?手動封裝一個JSONP的跨域請求函數。

  • 因爲瀏覽器出於安全考慮,有同源策略。也就是說,如果協議、域名或者端口有一個不同就是跨域,Ajax 請求會失敗。
  • 常用的跨域解決方案有:JSONP、CORS、代理。
  • JSONP跨域請求函數封裝如下:
# 使用JSONP(函數封裝)
function jsonp(url, jsonpCallback, success) {
  let script = document.createElement('script')
  script.src = url
  script.async = true
  script.type = 'text/javascript'
  window[jsonpCallback] = function (data) {
    success && success(data)
  }
  document.body.appendChild(script)
}
// 測試示例
jsonp('http://xxx', 'callback', function (value) {
  console.log(value)
})
# 使用JSONP(不封裝)
let script = document.createElement('script');
script.src = 'http://www.baidu.cn/login?username=JasonShu&callback=callback';
document.body.appendChild(script);
function callback (res) {
    console.log(res);
}


4、談一談 bind、call、apply的區別,並封裝實現一個 bind 函數。

  • call 和 apply 都是爲了解決改變 this 的指向。作用都是相同的,只是傳參的方式不同。除了第一個參數外,call 可以接收一個參數列表,apply 只接受一個參數數組。
let a = { value: 1 }
function getValue(name, age) {
    console.log(name)
    console.log(age)
    console.log(this.value)
}
getValue.call(a, 'geek', '10')
getValue.apply(a, ['geek', '30'])
  • bind 的實現對比其他兩個函數略微地複雜了一點,因爲 bind 需要返回一個函數,需要判斷一些邊界問題,參考代碼如下。
Function.prototype.myBind = function (context) {
  if (typeof this !== 'function') {
    throw new TypeError('Error')
  }
  const _this = this
  const args = [...arguments].slice(1)
  // 返回一個函數
  return function F() {
    // 因爲返回了一個函數,我們可以 new F(),所以需要判斷
    if (this instanceof F) {
      return new _this(...args, ...arguments)
    }
    return _this.apply(context, args.concat(...arguments))
  }
}


5、請繪製並描述Vuex的工作流程。


6、觀察下方示例代碼中的輸入與輸出關係,封裝 add() 方法。

add(1);       // 1
add(1)(2);    // 3
add(1)(2)(3); // 6
add(1)(2,3);  // 6
add(1,2)(3);  // 6
add(1,2,3);   // 6
function add() {
  let args = [].slice.call(arguments); 
  let fn = function(){
   let fn_args = [].slice.call(arguments)
   return add.apply(null,args.concat(fn_args))
  }
  fn.toString = function(){
    return args.reduce((a,b)=>a+b)
  }
  return fn
}
// 測試:
add(1,2)(3)(4,5)(6);   // 21


7、羅列 ES6 的新特性。

8、封裝函數,實現千位分隔符。

// 保留三位小數
parseToMoney(1234.56); // return '1,234.56'
parseToMoney(123456789); // return '123,456,789'
parseToMoney(1087654.32123); // return '1,087,654.321'
function parseToMoney(num) {
  num = parseFloat(num.toFixed(3));
  let [integer, decimal] = String.prototype.split.call(num, '.')
  integer = integer.replace(/\d(?=(\d{3})+$)/g, '$&,')
  return integer + '.' + (decimal ? decimal : '')
}


9、常用的 CSS 佈局屬性(方案)有哪些?

10、封裝方法求任意兩個Number數組的交集。

舉例:輸入 num1 = [1, 2, 2, 1]nums = [2, 2, 3],返回 [2, 2]

function union (arr1, arr2) {
  return arr1.filter(item => arr2.indexOf(item)>-1)
}
// 測試
const a = [1, 2, 2, 1];
const b = [2, 3, 2];
union(a, b)   // [2, 2]

本週結束,下週繼續!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章