前端基础面试题@JS篇

综合技术 2018-05-18

  • String
  • Number
  • Boolean
  • null
  • undefined
  • symbol

引用类型

  • object

说说Http状态码

1** 信息,服务器收到请求,需要请求者继续执行操作(101,升级为websocket协议)

2** 成功,操作被成功接收并处理(206,部分内容,分段传输)

3** 重定向,需要进一步操作以完成请求(301,302重定向;304,资源不存在)

4** 客户端错误,请求包含语法错误或无法完成请求(401,要求身份验证;403,服务器理解客服端需求,但是禁止访问)

5** 服务器错误,服务器在处理请求的过程中发生了错误

说说ajax状态码,ajax一定是异步的吗?

ajax不一定是异步的,可以通过open方法的第三个参数来配置(默认为true,异步)

状态码:

0 - (未初始化)还没有调用send()方法

1 - (载入)已调用send()方法,正在发送请求

2 - (载入完成)send()方法执行完成

3 - (交互)正在解析响应内容

4 - (完成)响应内容解析完成,可以在客户端调用了

说说ajax是什么?优势?劣势?应该注意的问题?

ajax是一种和后台通信的标准。全称是Asynchronous Javascript And XML(异步javascript和XML)。

优势:

  • 无需刷新页面请求数据,可以使产品更快、更小、更友好
  • 可以把以前服务端的任务转嫁到客户端来处理,减轻服务器负担,节省带宽
  • 浏览器支持好,无需插件

劣势:

  • 不支持浏览器的回退按钮
  • 安全性存在问题,能够在用户不知情的情况下发送请求
  • 暴露了http交互细节
  • 对搜索引擎(网络爬虫)的支持比较弱
  • 程序不容易调试

注意的问题:

  • 浏览器兼容性问题,这个问题jQuery等库已经帮我们封装好了
  • 跨域问题,不同域之间不允许通过ajax进行访问,可以参考阮一峰老师的 跨域资源共享 CORS 详解
  • 为了更快的速度和对搜索引擎友好,首页尽量不要用ajax而是服务端渲染(当然这看分场景)
  • ajax适合增删改查操作

你把下面的表达式的打印结果写出来

1.toString()  //Uncaught SyntaxError: Invalid or unexpected token
true.toString()  //"true"
[].toString()  //""
{}.toString()  //Uncaught SyntaxError: Unexpected token .
null.toString()  //Uncaught TypeError: Cannot read property 'toString' of null
undefined.toString()  //Uncaught TypeError: Cannot read property 'toString' of undefined
NaN.toString()   //"NaN"

这些需要刻意背一下,其中报错的这些都是因为没有 toString
方法。当然你可以使用 call
来借用,不过得到的是另外一种结果:

Object.prototype.toString.call(1)   //[object Number]
Object.prototype.toString.call({})   //[object Object]
Object.prototype.toString.call(null)   //[object Null]
Object.prototype.toString.call(undefined)   //[object Undefined]

前端性能优化你了解哪些

内容层面

  • 使用CDN
  • 单域名、多域名,单域名可以减少DNS查找次数,多域名可以增加浏览器并行下载数量,这需要权衡,一般同一个域下不要超过四个资源。
  • 避免重定向(分场景)
  • 避免404

网络层面

  • 利用缓存,可以参考另一篇文章 手写文件服务器,说说前后端交互
  • 文件压缩(通过响应头Accept-Encoding: gzip, deflate, br告诉服务器你支持的压缩类型)
  • 按需加载,提取公共代码,tree-shaking等(都可以通过webpack来实现)
  • 减少cookie大小
  • 文件合并,通过css雪碧图合并图片
  • 文件预加载、图片懒加载

渲染层间

  • js放底部,css放顶部
  • 减少reflow(回流)和repaint(重绘)
  • 减少dom节点

代码层面

  • 缓存dom节点,减少节点查找,css选择器层级优化
  • 减少dom节点操作
  • 合理使用break、continue、return等,优化循环
  • 像react用到的事件委托、对象池等手段

说说浏览器的reflow和repaint

浏览器解析过程

  1. 解析html生成dom树
  2. 解析css
  3. 把css应用于dom树,生成render树(这里记录这每一个节点和它的样式和所在的位置)
  4. 把render树渲染到页面

reflow(回流)

reflow翻译为回流,指的是页面再次构建render树。每个页面至少发生一次回流,就是第一次加载页面的时候

此外,当页面中有任何改变可能造成文档结构发生改变(即元素间的相对或绝对位置改变),都会发生reflow,常见的有:

  • 添加或删除元素(opacity:0除外,它不是删除)
  • 改变某个元素的尺寸或位置
  • 浏览器窗口改变(resize事件触发)

repaint(重绘)

repaint翻译为重绘,它可以类比为上面的第四步,根据render树绘制页面,它的性能损耗比回流要小。每次回流一定会发生重绘。此外,以下操作(不影响文档结构的操作,影响结构的会发生回流)也会发生重绘:

  1. 元素的颜色、透明度改变
  2. text-align等

浏览器优化

我们不太容易精确知道哪些操作具体会造成哪些元素回流,不同的浏览器都有不同的实现。但是确定是他们的的耗时是比较长的,因为涉及到大量的计算。

浏览器为了提升性能也对这个问题进行了优化。方案就是维护一个队列,把所有需要回流和重绘的操作都缓存起来,一段时间之后再统一执行。但是,有的时候我们需要获取一些位置属性,当我们一旦调用这些api的时候,浏览器不得不立即计算队列以保证提供的数据是准确的。例如以下操作:

  • offsetTop, offsetLeft, offsetWidth, offsetHeight
  • scrollTop/Left/Width/Height
  • clientTop/Left/Width/Height
  • width,height
  • getComputedStyle或者IE的currentStyle

注意问题

  1. 批量处理
  • 使用DocumentFragment进行缓存,这样只引发一次回流
  • 把频繁操作的元素先display:null,只引发两次回流
  • cloneNode和replaceChild,只引发两次回流
  1. 不要频繁更改style,而是更改class
  2. 避免频繁调用offsetTop等属性,在循环前把它缓存起来
  3. 绝对定位具有复杂动画的元素,否则会引起父元素和后续大量元素的频繁回流

如何去除字符串首位空格?

//es6
' ab '.trim()      //"ab" 
//正则
' ab '.replace(/^s*|s*$/g,'')  //"ab"

如何获取url中的查询字符串

function queryUrlParameter(str) {
    let obj = {}
    let reg = /([^?=&#]+)=([^?=&#]+)/g;
    str.replace(reg, function () {
        obj[arguments[1]] = arguments[2]
    })
    //如果加上hash
    // reg = /#([^?&=#]+)/g
    // if (reg.test(str)) {
    //     str.replace(reg, function () {
    //         obj.hash = arguments[1]
    //     })
    // }
    return obj
}
console.log(queryUrlParameter('http://www.baidu.com?a=1&b=2#12222'))  //{ a: '1', b: '2'}

如何实现一个深拷贝、深比较

深拷贝

function clone(obj) {
  if (obj == null || typeof obj !== 'object') return obj

  let newObj = null

  // 时间对象有特殊性
  if (obj.constructor === Date) {
    newObj = new obj.constructor(obj)
  } else {
    obj.constructor()
  }


  for (let key in Object.getOwnPropertyDescriptors(obj)) {
    newObj[key] = clone(obj[key])
  }
  return newObj
}

深比较

function deepCompare(a, b){
  if(a === null
    || typeof a !== 'object'
    || b === null
    || typeof b !== 'object'){
    return a === b
  }

  const propsA = Object.getOwnPropertyDescriptors(a)
  const propsB = Object.getOwnPropertyDescriptors(b)
  if(Object.keys(propsA).length !== Object.keys(propsB).length){
    return false
  }

  return Object.keys(propsA).every( key => deepCompare(a[key], b[key]))

}

如何实现函数节流和防抖

节流

function throttle(fn, delay) {
  delay = delay || 50
  let statTime = 0
  return function () {
    statTime === 0 && fn.apply(arguments)
    let currentTime = new Date()
    if (currentTime = statTime > delay) {
      fn.apply(arguments)
      statTime = currentTime
    }
  }
}

let throttleFn = throttle(fn)
throttleFn()
throttleFn()
throttleFn()
throttleFn()//只会执行一次

防抖

function debounce(fn, delay) {
  delay = delay || 50
  let timer = null
  return function () {
    let self = this
    clearTimeout(timer)
    timer = setTimeout(fn.bind(self, arguments), delay);
  }
}

你给我写一个原生bind方法

Function.prototype._bind = function (context) {
  let self = this
  let args_1 = [].prototype.slice.call(arguments, 1)
  return function () {
    let args_2 = [].prototype.slice.call(arguments)
    let args = args_1.concat(args_2)
    return this.apply(context, args)
  }
}

这只是对bind的一种简单实现,如果有兴趣了解更多可以参考 Javascript中bind()方法的使用与实现

如何实现一个数组的展平

function (ary) {
    return ary.toString().split(',')
}

这是一个投机取巧的方法(面试写个这个也凑合吧),如果有兴趣可以搜索一下其他实现方法

稀土掘金

责编内容by:稀土掘金 (源链)。感谢您的支持!

您可能感兴趣的

Combine browsing an image and upload See below code. There are two buttons. One button is to select an image and the second button is to ...
CRM Integration With the Big 3 in JavaScript CRM Integration With the Big 3 in JavaScript DZone's Guide to CRM Integration With the B...
Queering the Heatmap Over on Metafilter I learned about the project Queering the Map . I like it! Simple project to let ...
Define the header of the response content type in ... I have a use case where I make a cross domain JSONP request. $.ajax({ url: "http://anyorigin....
Migrating a REST API from Javascript to Haskell Background For just over a year, I’ve been running the JTime project , which consists of a RES...