前端面试题

1.H5 C3

**H5 **

Html5是Web中核心语言HTML的规范,是 HyperText Markup Language 5 的缩写,H5提供新的标签元素,使代码变的更有语义;提供了大量api,如本地存储、离线存储、webworker、websocket、filereader、地理定位、拖拽等;提供了更加酷炫的CSS3新特性,如过渡、变形、动画、阴影、渐变等。

CSS3 新特性

1、颜色: 新增 RGBA , HSLA 模式

2、文字阴影(text-shadow)

3、边框: 圆角(border-radius) 边框阴影 : box-shadow

4、盒子模型: box-sizing (content-box,border-box)

5、背景:background-size 、background-origin 、background-clip

6、渐变: linear-gradient , radial-gradient

7、过渡 : transition 可实现动画

8、自定义动画 animate :@keyfrom

9、媒体查询 多栏布局 @media screen and (width:800px) {…}

10、2D 转换;transform: translate(x,y) rotate(x,y) skew(x,y) scale(x,y)

11、3D 转换

12、弹性布局 flex

13、两栏自适应

1\ float+margin 左浮动+右边margin-left左边盒子宽度

​ .left{ float:left width:100px } .right{ margin-left:100px }

2\ float+overflow 左浮动+右溢出隐藏

​ .left{ float:left width:100px } .right{ overflow:hidden }

3\ flex 父元素(弹性盒子)+左(固定宽)+右(flex剩下所有空间)

​ .parent{ display:flex } .left{ width:100px } .right{ flex:1 }

2.闭包及优缺点

闭包:在一个函数中存放另外一个函数,在其内部生成一个局部作用域。在函数的外部可以直接访问这个函数中的变量。

应用场景:要获取某函数内部的局部变量

闭包的优点:1.能够读取函数内部的变量 2.让这些变量一直存在于内存中,不会在调用结束后,被垃圾回收机制回收

闭包的缺点:由于闭包会使函数中的变量保存在内存中,内存消耗很大,所以不能滥用闭包,解决办法是,退出函数之前,将不使用的局部变量删除。

function foo(){
        var a = 0;
        function f(){
          a++;
          return a;
        }
        return f;
      }
var res = foo();
res();	//1
res();	//2
res();	//3
console.log(res()); // 4 a的值被存储在内存中不会被释放掉
3.ES6的新增方法

1、新增声明命令 let 和 const

2、模板字符串(Template String):用一对反引号(`)标识,它可以当作普通字符串使用,也可以用来定义多行字符串

3、函数的扩展:箭头函数

4、对象的扩展:属性名和属性值相同时可以简写

5、Promise 对象:解决异步编程,,将异步操作以同步操作的流程表达出来。即解决异步处理回调地狱

6、解构赋值:数组和对象都可以用

7、…展开运算符可以将数组或对象里面的值展开;还可以将多个值收集为一个变量

8、async、await

9、set:它允许你存储任何类型的唯一值,无论是原始值或者是对象引用。map:对象保存键值对,任何值(对象或者原始值) 都可以作为一个键或一个值。

4.let/var/const区别
  • var 声明变量可以重复声明,而 let 不可以重复声明
  • var 是不受限于块级的,而 let 是受限于块级
  • var 会与 window 相映射(会挂一个属性),而 let 不与 window 相映射
  • var 可以在声明变量之前访问变量,而 let 有暂存死区,在声明之前访问变量会报错
  • const 声明之后必须赋值,否则会报错
  • const 定义不可变的量,改变了就会报错
  • const 和 let 一样不会与 window 相映射、支持块级作用域、在声明的上面访问变量会报错
5.promise的方法
const promise = new Promise(function (resolve, reject) {
  // ... some code 
  if (/* 异步操作成功 */) {
    resolve(value);
  } else {
    reject(error);
  }
});

实例的方法

  • .then((value)=>{}),取到的是 成功之后的结果,可以实现异步的深层嵌套, —人资笔记
  • .catch((errior)=>{})取到失败的结果是.then(null, rejection)的别名
  • .finnaly(()=>{})成功和失败最后都会执行这个方法

静态方法 (挂载到构造函数上面的 )

  • .all([])用于将多个 Promise 实例,包装成一个新的 Promise 实例
  • .race()只要有一个完成 就取到结果
6.跨域

由于浏览器的同源策略,防止他人恶意攻击网站

1、jsonp的原理: ajax请求受同源策略影响,不允许进行跨域请求,而script标签src属性中的链接却可以访问跨域的js脚本,利用这个特性,服务端不再返回JSON格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样实现了跨域。缺点:只能发起get请求,不能发起post请求

 //1.创建一个script标签 
var os=document.createElement("script")
//2.给script一个src,src就是地址,cb=回调函数 
os.src="http://suggestion.baidu.com/su?cb=qwer&wd=123" 
//3.将script插入到页面
document.body.appendChild(os) 
//4.回调函数处理数据 
function qwer(d){  //d就是后端返回的数据 }   

2、 CORS:设置后端。跨域资源共享:服务器设置 Access-Control-Allow-OriginHTTP 响应头之后,浏览器将会允许跨域请求

3、配置代理 :在vue.config.js中的devServer下的proxy中的api下的target配置跨域请求的地址,并设置changeOrigin: true

module.exports={  
    // hash模式,publicPath 配置为"";history模式。,需要配置为"/"  
    publicPath:"", 
    outputDir:"dist", 
    assetsDir:"public",
    indexPath:"index.html",
    //配置代理 
    devServer:{    
        proxy:{    
            "/api":{//拦截以/api开头的接口      
                target:"http://localhost:3000",//要跨域的域名 
                ws:true,//        
                changeOrigin:true // 是否开启跨域    
                }    
            } 
        } 
    }  
7.防抖节流

函数防抖:当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。最后一次操作能被触发

  function debounce(fun, delay) { 
      let timer = null  
      return function () {  
          if (timer) {  
              clearTimeout(timeoutId);  
          }   
          timer = setTimeout(() => {   
              fun.call(this)  
          }, delay) 
      } 
  };  

应用:搜索里面每输入一个字符就发起请求优化为以最后一次输入后为准

函数节流:当持续触发事件时,保证一定时间段内只调用一次事件处理函数节流。使得一定时间内只触发一次函数。

    function throttle(fun, delay) { 
        let flag = true 
        return function () {
            if (flag) { 
                setTimeout(() => { 
                    fun.call(this)  
                }, delay) 
            } 
        } 
    }   

应用:页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次,Ajax 求,而不是在用户停下滚动页面操作时才去请求数据

8.深拷贝和浅拷贝、原型链、递归(说出应用场景)

浅拷贝:只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块堆内存。 因此如果其中一个对象改变了这个地址,就会影响到另一个对象。

深拷贝:会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。深拷贝相比于浅拷贝速度较慢并且花销较大。

深拷贝的方法

  1. JSON.parse(JSON.stringify())将一个对象先转为json字符串,然后再转回来,这样可以实现深拷贝。但是这个方法有个缺陷,可以实现对象或数组的深拷贝,但是不能处理函数,函数经过这样处理后会变成null
  2. es6使用…

JavaScript 原型: 每个对象都会在其内部初始化一个属性,就是 prototype(原型)

原型链概念: 当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去 prototype 里找这个属性,这个 prototype又会有自己的 prototype,于是就这样一直找下去,直到为null

9.localstorage、sessionStorage、cookie 的区别
  • 共同点:都是保存在浏览器端、且同源的
  • 区别:

1、cookie 数据始终在同源的 http 请求中携带(即使不需要),即 cookie 在浏览器和服务器间来回传递,

​ 而 sessionStorage 和 localStorage 不会自动把数据发送给服务器,仅在本地保存。

​ cookie 数据还有路径(path)的概念,可以限制 cookie 只属于某个路径下

2、存储大小限制也不同,cookie 数据不能超过 4K,同时因为每次 http 请求都会携带 cookie、 所以 cookie 只适合保存很小的数据,如会话标识。

​ sessionStorage 和 localStorage 虽然也有存 储大小的限制,但比 cookie 大得多,可以达到 5M 或更大

3、数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效;

​ localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;

​ cookie:只在设置的 cookie 过期时间之前有效,即使窗口关闭或浏览器关闭

4、作用域不同,sessionStorage 不在不同的浏览器窗口中共享,即使是同一个页面;

​ localstorage 和cookie是在所有同源窗口中都是共享的

5、web Storage 支持事件通知机制,可以将数据更新的通知发送给监听者

6、web Storage 的 api 接口使用更方便

10.JS 执行机制(事件循环)

js执行流程

  1. 同步
  2. 微任务(Promise.then((res)=>{}),then后面的才是微任务,前面是同步)
  3. 宏任务(setTimeout,setInterval)

js执行机制

同步和异步任务分别进入不同的执行环境,同步的进入主线程,异步的进入任务队列。主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。 上述过程的不断重复就是我们说的 Event Loop (事件循环)。

11.一个页面从输入 URL 到页面加载显示完成过程中都发生了什么
  1. 浏览器地址栏输入url
  2. 浏览器会先查看浏览器缓存–系统缓存–路由缓存,如有存在缓存,就直接显示。如果没有,接着第三步
  3. 域名解析(DNS)获取相应的ip
  4. 浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手
  5. 握手成功,浏览器向服务器发送http请求,请求数据包
  6. 服务器请求数据,将数据返回到浏览器
  7. 浏览器接收响应,读取页面内容,解析html源码,生成DOm树
  8. 解析css样式、浏览器渲染,js交互绑定多个域名,数量不限;

三次握手(建立连接)

  1. 主机向服务器发送一个建立连接的请求(您好,我想认识您);
  2. 服务器接到请求后发送同意连接的信号(好的,很高兴认识您);
  3. 主机接到同意连接的信号后,再次向服务器发送了确认信号(我也很高兴认识您)

自此,主机与服务器两者建立了连接。

TCP 协议

三次握手的过程采用 TCP 协议,其可以保证信息传输的可靠性,三次握手过程中,若一方收不到确认信号,协议会要求重新发送信号。

四次挥手(断开连接)

  1. 主机向服务器发送一个断开连接的请求(不早了,我该走了);
  2. 服务器接到请求后发送确认收到请求的信号(知道了);
  3. 服务器向主机发送断开通知(我也该走了);
  4. 主机接到断开通知后断开连接并反馈一个确认信号(嗯,好的),服务器收到确认信号后断开连接;
12.Javascript 垃圾回收机制???

一般来说没有被引用的对象就是垃圾,就是要被清除, 有个例外如果几个对象引用形成一个环,互相引用,但根本访问不到它们,这几个对象也是垃圾,也要被清除。

垃圾回收的方法主要有两种:一种是标记清除,即用完之后的变量 赋值成null,另一种 是引用计数,将使用完的对象的引用计数,如果为0则回收

13.数组去重的方法

1.新建一个空的结果数组,for 循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则push进数组。

 function unique(arr) {  
     if (!Array.isArray(arr)) { 
         console.log('type error!')   
         return 
     } 
     var array = [];  
     for (var i = 0; i < arr.length; i++) { 
         if (array .indexOf(arr[i]) === -1) {  
             array .push(arr[i]) 
         } 
     }  
     return array; 
 }
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr)) // [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}] //NaN、{}没有去重   

2.双重for循环。双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。

    function unique(arr){   
        for(var i=0; i<arr.length; i++){
            for(var j=i+1; j<arr.length; j++){    
                if(arr[i]==arr[j]){   
                    //第一个等同于第二个,splice方法删除第二个 
                    arr.splice(j,1);   
                    j--;     
                }    
            }   
        }
        return arr;
    }
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr)) //[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}]   //NaN和{}没有去重,两个null直接消失了  

3.利用 filter

function unique(arr) {
    return arr.filter(function(item, index, arr) { 
        //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素  
        return arr.indexOf(item, 0) === index;  
    });
} 
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr)) //[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]     

4.使用es6语法中的Set()方法

    function unique (arr) { 
        return Array.from(new Set(arr))
                          } 
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; 
console.log(unique(arr))//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]        
14.双向绑定原理

采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty()来劫持各个属性的 setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。

MVVM 作为数据绑定的入口,整合Observer、Compile 和 Watcher三者,通过Observer 来监听自己的 model 数据变化,通过 Compile 来解析编译模板指令,最终利用 Watcher 搭起 Observer和 Compile 之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变(input) -> 数据 model变更的双向绑定效果

15.vue生命周期

Vue 实例从创建到销毁的过程,一共分为11个

beforeCreate(){}  //创建之前,什么都没有
created(){} //创建之后,数据初始化完成,但是el还是undefined       
//作用:二次修改初始值
beforeMount(){} //2.挂载期:如果有el或者$mount(),才自动触发 
//挂在之前:找到了要解析的模板,但是{{}} v-指令都还没有解析
mounted(){} //挂载完成:页面完成解析,DOM节点加载完成     
//作用:获取dom,添加动画,开启计时器,给window或者document绑定事件
beforeUpdate(){}  //3.更新期。数据变化了,但是页面准备重新渲染之前,注意,此时取到 的数据是新值 
updated(){}  //页面更新完成
beforeDestroy(){} //4.销毁期。作用:善后工作:1.清除计时器;2.清除window|document上的事件 
destroyed(){} //销毁完成    
 activated :keep-alive 组件激活时调用。该钩子在服务器端渲染期间不被调用
 deactivated :keep-alive 组件停用时调用。该钩子在服务器端渲染期间不被调用
 errorCaptured(2.5.0+ 新增) 当捕获一个来自子孙组件的错误时被调用。
 此钩子会收到三个参数:错误对象、发生 错误的组件实例以及一个包含错误来源信息的字符串,
 此钩子可以返回 false 以阻止该错误继续 向上传播  
16.Vue的基本原理,vue路由,vue组件传值
  • Vue的基本原理:Vue的数据驱动是通过MVVM模式来实现的;

  • Vue 的路由实现模式:hash 模式和 history 模式(必会)

    hash  http://baidu.com/#/login
    1.前进 后退 刷新  都ok
    2.#/login 是hash值,hash值是不会影响请求
    3.采用的是window.onhashchange=()=>{} 原理实现,是可以兼容IE678的
    
    history http://baidu.com/login
    1.前进 后退 ok   刷新:如果后端有这个路由,就会直接展示后端数据到页面;如果后端没有这个路由,404.
    /login 是会影响请求
    采用的是HTML5新增的API interface (pushState replaceState)
    如果想使用history模式,需要后端配合。
    
  • vue组件传值

父传子 :在父组件引用的子组件上绑定一个自定义属性并把数据绑定在自定义属性上,在子组件添加参数 props(type,required) 接收即可

子传父 :子组件通过this.$emit进行触发自定义事件并且可以携带参数,父组件监听使用@(v-on) 进行监听,然后进行方法处理

17.v-show 和 v-if 指令的共同点和不同点

​ 1、相同点: v-show 和 v-if 都能控制元素的显示和隐藏。

​ 2、不同点:

​ 2.1)实现本质方法不同

​ v-show 本质就是通过设置 css 中的 display 设置为 none,控制隐藏

​ v-if 是动态的向 DOM 树内添加或者删除 DOM 元素

​ 2.2)编译的区别

​ v-show 其实就是在控制 css

​ v-if 切换有一个局部编译/卸载的过程,切换过程中合适地销毁和重建内部的事件监听和子组件

​ 2.3)编译的条件

​ v-show 都会编译,初始值为 false,只是将 display 设为 none,但它也编译了

​ v-if 初始值为 false,就不会编译了

​ 2.4)性能比较

​ v-show 只编译一次,后面其实就是控制 css,而 v-if 不停的销毁和创建,故 v-show 性能更好。

​ 3、因为 v-show 实际是操作 display:" "或者 none,当 css 本身有 display:none 时,v-show 无法让显示

​ 4、总结(适用场景):

​ 如果要频繁切换某节点时,使用 v-show(无论 true 或者 false 初始都会进行渲染,此 后通过 css 来控制显示隐藏,因此切换开销比较小,初始开销较大),

​ 如果不需要频繁切换某节 点时,使用 v-if(因为懒加载,初始为false 时,不会渲染,但是因为它是通过添加和删除 dom 元素来控制显示和隐藏的,因此初始渲染开销较小,切换开销比较大)

18.Vuex 的 5 个核心属性

分别是 State、 Getter、Mutation 、Action、 Module

Vuex使用单一状态树,即用一个对象就包含了全部的状态数据。

- state定义了所有我们需要的基本状态参数。
- getter导出数据
- mutation更改 store 中 state状态。
内容方法名(state,形参) { state.数据 = 形参}
使用:store.commit('方法',实参)
- action 异步操作。
一般用于做逻辑操作,调用mutation中的方法修改state
内容:方法名(context,形参) {}
使用:store.dispatch("方法",实参)
- module 解决了当 state 中很复杂臃肿的时候,module 可以将 store 分割成模块,每个模块中拥有自己的 state、mutation、action 和 getter
19.Vue 常用的修饰符都有哪些

.prevent: 提交事件不再重载页面;

.stop: 阻止单击事件冒泡;

.self: 当事件发生在该元素本身而不是子元素的时候会触发;

.capture: 事件侦听,事件发生的时候会调用

项目
1.如何进行前端性能优
  1. 代码压缩合并
  2. 启用Gzip压缩
  3. 函数防抖实现搜索优化,减少http请求
  4. 使用CDN资源代替本地资源
  5. 使用精灵图代替小图标
  6. 图片很多的时候使用懒加载
2.项目中遇到的问题和解决方式
  • vue项目中用v-for 循环本地图片, 图片不显示,解决办法:使用require()动态引入图片[img v-bind:src=“require(item.imgurl)”](img v-bind:src=“require(item.imgurl)”)

  • 不同组件样式相互影响,即样式污染。 解决:在当前组件中的style中,加scoped标识

  • 首页白屏:由于浏览器在渲染出页面之前,需要先加载和解析相应的html,css和js文件,为此会有一段白屏的时间。解决办法:添加路由懒加载,组件异步加载 ,减少http请求,添加一个loading动画

  • 页面刷新vuex被清空

    • 一种方法就是用localStorage。
    • 也可需要某些数据之前先判断一下数据是否存在,如果不存在重新获取
  • 错误处理

由于我的请求是使用axios 单独写在了一个js,可以对其进行响应拦截。一旦失败,或者后台报错,就进行响应的错误处理以及友好提示,也避免了重复的代码,提高可维护性

3.token存储

项目中使用的token , 由于涉及到鉴权 ,需要在多个地方使用token这里把token存储到本地存储和 vuex 中【vuex刷新重置】

4.请求拦截器
  axios.interceptors.request.use(config => {  
      if (config.url !== "/api/login" && config.url !== "/api/register") {   
          config.headers.authorization = JSON.parse(localStorage.getItem("user")).token 
      }  
      return config;
  })  
5.响应拦截器
 axios.interceptors.response.use(res => { 
     //打印   
     console.log("本次请求地址:" + res.config.url);  
     console.log(res);   
     //失败处理  
     if (res.data.code !== 200) {  
         Toast(res.data.msg)
     }  
     return res;
 })  
6.项目收获
  1. 每个步骤环环相扣,每个职位都需要和其前后的人沟通协调。
  2. 必要的注释,方便自己方便他人。
  3. 变量、常量初始化、全局函数尽量放在最上层。
  4. 整体把控、注重命名和重用,出现觉得不合理的和需要重用的就应该优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值