常见面试题

常见面试题

1. 如何实现ajax请求
  • 通过实例化一个XMLHttpRequest对象得到一个实例
  • 调用实例的open方法为这次 ajax请求设定相应的http方法、相应的地址和以及是否异步,当然大多数情况下我们都是选异步
  • 以异步为例,之后调用send方法ajax请求,这个方法可以设定需要发送的报文主体
  • 然后通过 监听readystatechange事件,通过这个实例的readyState属性来判断这个ajax请求的状态,其中分为0,1,2,3,4这四种 状态,当状态为4的时候也就是接收数据完成的时候,这时候可以通过实例的status属性判断这个请求是否成功
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var xhr = new XMLHttpRequest();
    xhr.open('get', 'aabb.php', true);
    xhr.send(null);
    xhr.onreadystatechange = function() {
    if(xhr.readyState==4) {
    if(xhr.status==200) {
    console.log(xhr.responseText);
    }
    }
    }
javascript有哪几种数据类型

六种基本数据类型

  • undefined
  • null
  • string
  • boolean
  • number
  • symbol(ES6)

一种引用数据类型

  • Object
    什么闭包,闭包有什么用
    闭包是在某个作用域内定义的函数,它可以访问这个作用域内的所有变量。闭包作用域链通常包括三个部分:
  1. 函数本身作用域。
  2. 闭包定义时的作用域。
  3. 全局作用域。

闭包常见用途:

  1. 创建特权方法用于访问控制
  2. 事件处理程序及回调

JavaScript有哪几种方法定义函数

  1. 函数声明
  2. 函数表达式
  3. ES6箭头函数
客户端存储localStorage和SessionStorage
  • localStorage有效期为永久,sessionStorage有效期为顶层窗口关闭前
  • 同源文档可以读取并修改localStorage数据,sessionStorage只允许同一个窗口下的文档访问,如通过iframe引入的同源文档。
  • Storage对象通常被当做普通javascript对象使用:通过设置属性来存取字符串值,Storage对象的API:setItem(key, value)设置,getItem(key)读取,removeItem(key)删除,clear()删除所有数据,length表示已存储的数据项数目,key(index)返回对应索引的key
    1
    2
    3
    4
    5
    // 枚举所有存储的键值对
    for (var i = 0, len = localStorage.length; i < len; ++i ) {
    var name = localStorage.key(i);
    var value = localStorage.getItem(name);
    }
cookie及其操作
  • cookie是web浏览器存储的少量数据,最早设计为服务器端使用,作为HTTP协议的扩展出现。cookie数据会自动在浏览器和服务器之间传输。
  • 通过读写cookie检测是否支持
  • document.cookie setItem参数有key,value,max-age,path,domain
    link与@import的区别
  1. link是HTML方式, @import是CSS方式
  2. link最大限度支持并行下载,@import过多嵌套导致串行下载,出现FOUC
  3. link可以通过rel=”alternate stylesheet”指定候选样式
  4. 浏览器对link支持早于@import,可以使用@import对老浏览器隐藏样式
  5. @import必须在样式规则之前,可以在css文件中引用其他文件
  6. 总体来说:link优于@import
MVVM

mvvm由以下三个内容组成

  • View:界面
  • Model:数据模型
  • ViewModel:作为桥梁负责沟通View和Model

在jQuery时期,如果需要刷新UI时,需要先取到对应的DOM再更新UI,这样数据和业务的逻辑就和页面有强耦合。
在MVVM中,UI是通过数据驱动的,数据一旦改变就会相应的刷新对应的UI,UI如果改变,也会改变对应的数据。这种方式就可以在业务处理中只关心数据的流转,而无需直接和页面打交道。ViewModel只关心数据和业务的处理,不关心View如何处理数据,这种情况下,View和Model都可以独立出来,任何一方改变了也不一定需要改变另一方,并且可以将一些可复用的逻辑放在一个ViewModel中,让多个View复用这个ViewModel。
在MVVM中,最核心的也就是数据双向绑定,例如Angluar的脏数据检测,Vue中的数据劫持。

脏数据检测
数据劫持

Vue内部使用了Object.definpropty() 中的get和set方法监听数据。
在解析模板代码时,会实例化属性的watcher对象,并且把它挂在到Dep.target属性上。
通过触发属性的get取值函数把相关的watcher实例添加到dep的subs属性中。
当数据发生变化时,触发属性的set存值函数,调用dep对象的notify方法,主要内容是遍历相关的watcher实例,调用其对应的update方法,更新视图。

面向过程和面向对象的区别?

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个调用就可以了。
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。

箭头函数表达式和普通函数的区别

箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super或 new.target。
更短的函数、不绑定this、通过 call 或 apply 调用第一个参数忽略、不绑定arguments、箭头函数不能用作构造器,和 new一起用会抛出错误、箭头函数没有prototype属性、箭头函数不能用作生成器

vdom是什么?为何会存在vdom?

不用vdom遇到的问题:

  • DOM操作是“昂贵”的,js运行效率高
  • 尽量减少DOM操作,而不是“推到重来”
  • 项目越复杂,影响就越严重
  • vdom即可解决这个问题
    问题解答:
  • virtual dom,虚拟DOM
  • 用JS模拟DOM结构
  • DOM操作非常“昂贵”
  • 将DOM对比操作放在JS层,提高效率
    vdom如何应用,核心API是什么?
  • h(‘<标签名>’, {…属性…}, […子元素…])
  • h(‘<标签名>’, {…属性…}, ‘…’)
  • patch(container, vnode)
  • patch(vnode, newVnode)
    问题解答:
  • 如何使用?可用snabbdom的用法来举例
  • 核心API:h函数返回vnode、patch函数打补丁
    介绍一下diff算法?
    问题解答:
  • 知道什么是diff算法,是linux的基础命令
  • vdom中应用diff算法是为了找出要更新的节点
  • diff实现,patch(container, vnode) patch(vnode, newVnode)
  • 核心逻辑,createElement和updateChildren
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    function createElement(vnode) {
    var tag = vnode.tag
    var attrs = vnode.attrs || {}
    var children = vnode.children || []
    if (!tag) {
    return null;
    }
    // 创建元素
    var elem = document.createElement(tag)
    // 属性
    var attrName
    for (attrName in attrs) {
    if (attrs.hasOwnProperty(attrName)) {
    elem.setAttribute(attrName, attrs[attrName])
    }
    }
    // 子元素
    children.forEach(function(childVnode) {
    // 递归调用createElement创建子元素
    elem.appendChild(createElement(childVnode))
    })
    return elem;
    }