让前端飞Web前端之路

前端常见面试题 (一)

2019-06-28  本文已影响66人  郝晨光
  1. HTML5有哪些新特性?如何处理HTML5新标签的浏览器兼容问题?如何区分HTML和HTML5?

    1. 新特性

      1. 绘画 canvas,svg;

      2. 用于媒体播放的的 video(视频) 和 audio(音频) 元素;

      3. 本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;

      4. sessionStorage 存储会话级数据,数据在浏览器关闭后自动删除;

      5. 语意化更好的内容元素,比如 article、footer、header、nav、section;

      6. 新增的表单控件,calendar、date、time、email、url、search;

      7. 新增的表单属性, form、formtarget、autofocus、required、placeholder、autoComplete、pattern

      8. 新的技术webworker(js创建的多线程环境), websocket(前后端通讯协议,允许后端主动发送消息), Geolocation(地理位置);

    2. 兼容性问题

      1. 通过document.createElement方法可以创建HTML5新标签,但是创建的标签需要提前添加标签默认的样式。

      2. 也可以通过各种框架实现

      3. <!--[if lt IE 9]>
        
           <script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script>
        
        <![endif]-->
        
    3. 区分HTML和HTML5

      1. 通过<!Doctype html>文档声明来区分

      2. HTML5字符编码格式通过 <meta charset="UTF-8">来指定

      3. 通过HTML5新增的标签来区分

  2. css3中的transform有哪些属性?分别用来实现什么效果?

    1. 旋转rotate()函数

      • 通过指定的角度参数对原元素指定一个2D rotation(2D 旋转),需先有transform-origin属性的定义。transform-origin定义的是旋转的基点,其中angle是指旋转角度,如果设置的值为正数表示顺时针旋转,如果设置的值为负数,则表示逆时针旋转。如:transform:rotate(30deg):
    2. 扭曲skew()函数

      • skew(x,y)使元素在水平和垂直方向同时扭曲(X轴和Y轴同时按一定的角度值进行扭曲变形);skewX(x)仅使元素在水平方向扭曲变形(X轴扭曲变形);skewY(y)仅使元素在垂直方向扭曲变形(Y轴扭曲变形)
    3. 缩放 scale()函数

      • scale(x,y)使元素水平方向和垂直方向同时缩放(也就是X轴和Y轴同时缩放);scaleX(x)元素仅水平方向缩放(X轴缩放);scaleY(y)元素仅垂直方向缩放(Y轴缩放),但它们具有相同的缩放中心点和基数,其中心点就是元素的中心位置,缩放基数为1,如果其值大于1元素就放大,反之其值小于1,元素缩小
    4. 偏移translate()函数

      • 移动translate我们分为三种情况:translate(x,y)水平方向和垂直方向同时移动(也就是X轴和Y轴同时移动);translateX(x)仅水平方向移动(X轴移动);translateY(Y)仅垂直方向移动(Y轴移动)
    5. 矩阵变形matrix() 函数

      • 以一个含六值的(a,b,c,d,e,f)变换矩阵的形式指定一个2D变换,相当于直接应用一个[a b c d e f]变换矩阵。就是基于水平方向(X轴)和垂直方向(Y轴)重新定位元素,此属性值使用涉及到数学中的矩阵
    6. 指定transform的基点 transform-origin

      • transform-origin(X,Y):用来设置元素的运动的基点(参照点)。默认点是元素的中心点。其中X和Y的值可以是百分值,em,px,其中X也可以是字符参数值left,center,right;Y和X一样除了百分值外还可以设置字符值top,center,bottom
  3. localStorage、sessionStorage、cookie有什么区别?

    1. localStorage生命周期是永久,这意味着除非用户显示在浏览器提供的UI上清除localStorage信息,否则这些信息将永远存在。存放数据大小为一般为5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。

    2. sessionStorage仅在当前会话下有效,关闭页面或浏览器后被清除。存放数据大小为一般为5MB,而且它仅在客户端(即浏览器)中保存,不参与和服务器的通信。源生接口可以接受,亦可再次封装来对Object和Array有更好的支持。

    3. 作用域不同

      不同浏览器无法共享localStorage或sessionStorage中的信息。相同浏览器的不同页面间可以共享相同的 localStorage(页面属于相同域名和端口),但是不同页面或标签页间无法共享sessionStorage的信息。这里需要注意的是,页面及标 签页仅指顶级窗口,如果一个标签页包含多个iframe标签且他们属于同源页面,那么他们之间是可以共享sessionStorage的。

    4. 生命期为只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。 存放数据大小为4K左右 。有个数限制(各浏览器不同),一般不能超过20个。与服务器端通信:每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题。但Cookie需要程序员自己封装,源生的Cookie接口不友好(http://www.jb51.net/article/6... )。

    5. cookie的优点:具有极高的扩展性和可用性

    1.通过良好的编程,控制保存在cookie中的session对象的大小。
    2.通过加密和安全传输技术,减少cookie被破解的可能性。
    3.只有在cookie中存放不敏感的数据,即使被盗取也不会有很大的损失。
    4.控制cookie的生命期,使之不会永远有效。这样的话偷盗者很可能拿到的就 是一个过期的cookie。</pre>

    1. cookie的缺点

    1.cookie的长度和数量的限制。每个domain最多只能有20条cookie,每个cookie长度不能超过4KB。否则会被截掉。
    2.安全性问题。如果cookie被人拦掉了,那个人就可以获取到所有session信息。加密的话也不起什么作用。
    3.有些状态不可能保存在客户端。例如,为了防止重复提交表单,我们需要在服务端保存一个计数器。若吧计数器保存在客户端,则起不到什么作用。</pre>

    7.** localStorage、sessionStorage、Cookie共同点:都是保存在浏览器端,且同源的。**

  4. 什么是同源策略?你都知道哪些解决跨域的方法?

    • 什么是同源策略? 同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个IP地址,也非同源

    • 同源策略限制以下几种行为:

      cookie、localStorage 和 indexDB 无法读取

      DOM 和 Js对象无法获得 ajax 请求不能发送

      URL 说明 是否允许通信
      http://www.baidu.com/a.js http://www.baidu.com/b.js http://www.baidu.com/lab/c.js 同一域名,不同文件或路径 允许
      http://www.baidu.com:8000/a.js http://www.baidu.com:8081/b.js 同一域名,不同端口 不允许
      http://www.baidu.com/a.js http://192.168.1.2/b.js 域名和域名对应相同IP 不允许
      http://www.baidu.com/a.js https://www.baidu.com/b.js 同一域名,不同协议 不允许
      http://www.baidu.com/a.js http://news.baidu.com/b.js 主域相同,子域不同 不允许
      http://www.baidu.com/a.js http://www.xina.com/b.js 不同域名 不允许
    • 1、 通过jsonp跨域

      • jsonp的原理:

      • script 标签的src属性可以跨域引用文件,jsonp是请求之后后台包装好一段json,并且把数据放在一个callback函数,返回一个js文件,动态引入这个文件,下载完成js之后,会去调用这个callback,通过这样访问数据。

      • 在浏览器端定义一个回调函数,并将函数名通过src传至服务器端;服务器端将数据包装成为一段js数据,并返回js函数格式的js文件,接着拿到这个js文件之后函数自动调用,拿到后端返回的数据

    • 2、 document.domain + iframe跨域

    • 3、 location.hash + iframe

    • 4、 window.name + iframe跨域

    • 5、 postMessage跨域

    • 6、 跨域资源共享(CORS)

      • 普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。

        需注意的是:由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,而非当前页。如果想实现当前页cookie的写入,可参考下文:七、nginx反向代理中设置proxy_cookie_domain 和 八、NodeJs中间件代理中cookieDomainRewrite参数的设置。

        目前,所有浏览器都支持该功能(IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)),CORS也已经成为主流的跨域解决方案。

    • 7、 nginx代理跨域

      • nginx反向代理接口跨域
      • 跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。

        实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。

    • 8、 nodejs中间件代理跨域

    • 9、 WebSocket协议跨域

      • WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯,允许服务器端主动向浏览器端发送消息。

  5. 列举JavaScript的基本数据类型和引用数据类型

    1. 基本数据类型

      1. number

      2. string

      3. boolean

      4. null

      5. undefined

      6. symbol

    2. 引用数据类型

      1. object

      2. function

      3. array

      4. map

      5. set

  6. Vue2.0的生命周期有哪些?分别解释其意思

    1. beforeCreate Vue实例创建之前,此时访问不到数据

    2. created Vue实例创建完成,此时已经可以访问到data和methods等

    3. beforeMount Vue实例的挂载到真实DOM结构之前

    4. mounted Vue实例的挂载到真实的DOM节点完成之后

    5. beforeUpdate Vue实例的数据修改,DOM修改之前

    6. updated Vue实例的数据修改完成,重新render之后

    7. beforeDestory Vue实例卸载之前

    8. destoryed Vue实例卸载完成

    9. activated 当使用keep-alive组件的时候,才会有的生命周期钩子,表示组件激活时

    10. deactivated 当使用keep-alive组件的时候,才会有的生命周期钩子,表示组件取消激活时

    11. errorCaptured (2.5+) 补获错误边界钩子,当子孙组件报错的时候,父组件会触发这个钩子函数,并返回三个参数,第一个参数是 错误对象第二个参数是 报错的子孙组件第三个参数是 报错的子孙组件的具体哪个地方报错。

    12. serverPrefetch (2.6+) 用来处理ssr,允许在渲染过程中等待异步数据

    13. Vue的生命周期钩子有合并策略,比如,父组件的生命周期和子组件的生命周期会合并成一个数组依次执行,所以,我们在定义生命周期钩子的时候,不仅可以定义一个函数,还可以定义一个数组

    14.     created: [
          function() {console.log(1)},
          function() {console.log(2)},
          function() {console.log(3)}
         ]
      
  7. 详述组件通信

    1. 父传子,父组件通过自定义属性的方式传递给子组件,子组件通过props接收,props一般使用对象的形式,通过parent和children来传值

      •  export default {
                name: 'child'
                props: {
                  list: {
                  type: Array, // 定义数据类型,可以是绝大部分javascript数据类型
                  required: true, // 属性是必须的
                  default: [1,2,3], // 默认值 
                  validator: function(value) {
                  // 自定义校验规则,返回true表示校验通过,返回false表示校验出错
                  if(value.indexOf(1)>-1) {
                    return true
                  }else {
                    return false
                  }
                 } 
              }
          }
        }
        
    2. 子传父,子组件通过 $emit向父组件发布事件,而父组件通过 v-on监听对应的事件,并触发函数,得到子组件发布的事件携带的值,通过parent和children来传值

    3. 兄弟组件通信

      1. 通过父组件进行中转

      2. 通过中央通信总线的方式,在需要通信的组件内使用 emit 和on 来发布和监听事件,并进行通信传值

      3. 通过Vuex来通信

        •   // 中央通信总线
            Vue.prototype.$bus = new Vue({});
            // 组件A
            this.$bus.$emit('handleClick',1);
            // 组件B
            this.$bus.$on('handleClick',value => {
             console.log(value);
            })
          
  8. 详述导航守卫

    1. 全局导航守卫

      1. router.beforeEach 全局前置守卫 当一个导航触发时,前置守卫最先触发

        • 一般在这个守卫方法中进行全局拦截,比如必须满足某种条件(用户登录等)才能进入路由的情况

        • router.beforeEach((to, from, next) => {
              console.log('全局前置守卫:beforeEach -- next需要调用')
              next()
           })
          
      2. router.beforeResolve (v 2.5.0+) 全局解析守卫 和beforeEach类似,区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用 即在 beforeEach 和 组件内beforeRouteEnter 之后

      3. router.afterEach 全局后置守卫 在所有路由跳转结束的时候调用

    2. 路由导航守卫

      1. beforeEnter 路由前置守卫 可直接定义在路由配置上,和beforeEach方法参数、用法相同
    3. 组件路由首页

      • beforeRouteEnter 在渲染该组件的对应路由被确认前调用,用法和参数与beforeEach类似

      • 注意:

        • 此时组件实例还未被创建,不能访问this

        • 可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数

        •  beforeRouteEnter (to, from, next) {
                // 这里还无法访问到组件实例,this === undefined
                next( vm => {
                // 通过 `vm` 访问组件实例
                })
             }
          
        • 可以在这个守卫中请求服务端获取数据,当成功获取并能进入路由时,调用next并在回调中通过 vm访问组件实例进行赋值等操作

        • beforeRouteEnter触发在导航确认、组件实例创建之前:beforeCreate之前;而next中函数的调用在mounted之后:为了确保能对组件实例的完整访问

      • beforeRouteUpdate 在当前路由改变,并且该组件被复用时调用

        • 对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,组件实例会被复用,该守卫会被调用

        • 当前路由query变更时,该守卫会被调用

      • beforeRouteLeave 导航离开该组件的对应路由时调用,可以访问组件实例 thisnext需要被主动调用,不能传回调

  9. v-show和v-if有什么区别?及使用场景

    1. v-if是通过添加和删除DOM节点来控制显示隐藏,v-show是通过操作css的display属性来控制显示隐藏;

    2. v-if拥有更高的切换成本,v-show拥有更高的渲染成本;

    3. 当组件或DOM不需要经常进行切换的时候,使用v-if;当组件或DOM需要经常进行切换的时候,使用v-show。

  10. v-for和v-if的优先级

    1. v-for的优先级更高,会先进行循环,再进行 if 判断

    2. 永远不建议同时使用 v-for 和 v-if ,因为会导致性能低下,增加渲染成本

    3. 当真的需要进行判断是否渲染列表的时候,在列表循环的外部添加 v-if

      •     <template>
               <div>
                   <ul v-if="list.length>5">
                       <li v-for="(item,index) in list" :key=index>{{item}}</li>
                 </ul>
             </div>
          </template>
        
    4. 当需要对循环的每一项进行判断是否渲染的时候,在computed计算属性中先行计算,并直接渲染对应的计算属性即可

      • <template>
             <div>
                 <ul>
                     <!--不建议这么写
                     <li v-for="(item,index) in list" v-if="item>5" :key=index>{{item}}</li>
                      -->
                      <li v-for="(item,index) in showList" :key=index>{{item}}</li>
                 </ul>
             </div>
          </template>
          ​
          <script>
          export default {
             name: 'App',
             data() {
               return {
                   list: [1,2,3,4,5,6,7,8,9,10]
                }
             },
             computed: {
               showList() {
                     return this.list.filter(item => item>5);
               }
             }
          }
          </script>
        

结言

上一篇下一篇

猜你喜欢

热点阅读