2019-03-04面试总结

219 阅读10分钟

  • 什么是伪数组

1.具有length属性
2.按照索引方式存储数据
3.不具备pop,push方法

伪数组无法直接调用数组方法或期望length属性有什么特殊的行为,
不具有数组的push()、pop()等方法,但仍可以对真正数组遍历方法来遍历它们。
这种对象有很多,比较特别的是function内的arguments对象,
还有像调用getElementsByTagName, document.childNodes之类的,
它们都返回的NodeList对象都属于伪数组,也称为类数组,还有自定义的对象,
也属于伪数组。
我们可以通过Array.prototype.slice.call(fakeArray)将伪数组转变为真正的
Array对象。 

  • 伪数组转换成数组

1.遍历,
2.Array.prototype.slice.call(oldArr)
3.es6新方法,newArr = Array.from(oldArr)
4.oldArr._proto_ = Array.prototype· 具有length属性;

  • 状态码js从数组中取出n个不重复的数据

/** * 数组去重,取出随机个数 */

 function unique(arr) {return [...new Set(arr)]}
function filterData(arr, number) {
    let unique_data = unique(arr)
    if (number >= unique_data.length) {
        reture
    }
    let new_arr = []
    let random, tempData
    for (let i = 0; i < number; i++) {
        random = parseInt(Math.random() * (unique_data.length - 1))
        tempData = unique_data.splice(unique_data[random], 1)
        new_arr.push(tempData[0])
    }
    return new_arr
}
console.log(filterData([1,2,3,4,5,6,7,8,"9aa","sdd","aaq","qq","ww","e","r","t","y","u","i","v","b","n","j","k","i",{"a":1},{"b":2}], 10))</

  • typeof 与instanceof区别


typeof() 是一个一元运算,放在一个运算数之前,运算数可以是任意
类型。它返回值是一个字符串,该字符串说明运算数的类型。
instanceof 用于判断一个变量是否某个对象的实例,

创建对象三种形式

Object.create()
字面量形式
构造函数形式

不使用第三变量交换值

方法一:var a=2,b=3;a=[b, b=a][0]; //地址指向,必须为对象
方法二:ES6解构赋值var a = 2, b = 3;  [a, b] = [b, a];

 防抖和节流

所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次, 如果在 n 秒
内又触发了事件,则会重新计算函数执行时间。
防抖分为立即执行和非立即执行
非立即执行
非立即执行版的意思是触发事件后函数不会立即执行,而是在 n 秒后执行,
如果在 n 秒内又触 发了事件,则会重新计算函数执行时间。
立即执行版的意思是触发事件后函数会立即执行,然后 n 秒内不触发事件
才能继续执行函数的效果。

<div id="content" style="height:150px;line-height:150px;text-align:center; color: #fff;background-color:#ccc;font-size:80px;"></div>
<script>
    let num = 1;
    let content = document.getElementById('content');

    function count() {
        content.innerHTML = num++;
    };
    content.onmousemove = count;
</script>
//非立即执行
function debounce(func, wait) {
    let timeout;
    return function () {
        let context = this;
        let args = arguments;

        if (timeout) clearTimeout(timeout);
        
        timeout = setTimeout(() => {
            func.apply(context, args)
        }, wait);
    }
}

content.onmousemove = debounce(count,1000);
//立即执行
function debounce(func,wait) {
    let timeout;
    return function () {
        let context = this;
        let args = arguments;

        if (timeout) clearTimeout(timeout);

        let callNow = !timeout;
        timeout = setTimeout(() => {
            timeout = null;
        }, wait)

        if (callNow) func.apply(context, args)
    }
}
/**
 * @desc 函数防抖
 * @param func 函数
 * @param wait 延迟执行毫秒数
 * @param immediate true 表立即执行,false 表非立即执行
 */
function debounce(func,wait,immediate) {
    let timeout;

    return function () {
        let context = this;
        let args = arguments;

        if (timeout) clearTimeout(timeout);
        if (immediate) {
            var callNow = !timeout;
            timeout = setTimeout(() => {
                timeout = null;
            }, wait)
            if (callNow) func.apply(context, args)
        }
        else {
            timeout = setTimeout(function(){
                func.apply(context, args)
            }, wait);
        }
    }
}

所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。

对于节流,一般有两种方式可以实现,分别是时间戳版和定时器版。

时间戳版:

function throttle(func, wait) {
    let previous = 0;
    return function() {
        let now = Date.now();
        let context = this;
        let args = arguments;
        if (now - previous > wait) {
            func.apply(context, args);
            previous = now;
        }
    }
}

定时器版:

function throttle(func, wait) {
    let timeout;
    return function() {
        let context = this;
        let args = arguments;
        if (!timeout) {
            timeout = setTimeout(() => {
                timeout = null;
                func.apply(context, args)
            }, wait)
        }

    }
}


  • 输出以下值的内容

{} == {}   //false
[] == []   //false
null == null  // true
undefined == undefined  // true
null == undefined // true
NaN == NaN // false

cookie, sessionStorage, localStorage区别

cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)
上的数据(通常经过加密)。cookie数据始终在同源的http请求中携带
(即使不需要),记会在浏览器
和服务器间来回传递。sessionStorage和localStorage不会自动把数据
发给服务器,仅在本地
保存。存储大小:cookie数据大小不能超过4k。sessionStorage和
localStorage 虽然也有存储大小的限制,但比
cookie大得多,可以达到5M或更大。有期时间:localStorage 存储
持久数据(目前业界基本上统一为5M),浏览器关闭后
数据不丢失除非主动删除数据;sessionStorage 数据在当前浏览器窗口
关闭后自动删除。cookie 设置的cookie过期时间之前一直有效,即使窗
口或浏览器关闭cookie在浏览器和服务器间来回传递。 sessionStorage和
localStorage不会sessionStorage和localStorage的存储空间更大;
sessionStorage和localStorage有更多丰富易用的接口;sessionStorage
和localStorage各自独立的存储空间;


  • web提高页面加载速度

一、减少HTTP请求
二、使用CDN
三、添加Expires头四、压缩组件五、将样式表放在头部六、将脚本放在底部七、避免CSS表达式八、使用外部的JavaScript和CSS九、减少DNS查找十、精简JavaScript十一、避免重定向十二、删除重复脚本十三、配置ETag


  • VUE history模式与hash模式区别

hash模式url里面永远带着#号,我们在开发当中默认使用这个模式。那么什么时候要用history模式呢?
如果用户考虑url的规范那么就需要使用history模式,因为history模式没有#号,是个正常的url适合推广宣
传。当然其功能也有区别,比如我们在开发app的时候有分享页面,那么这个分享出去的页面就是用vue或
是react做的,咱们把这个页面分享到第三方的app里,有的app里面url是不允许带有#号的,所以要将#号去除
那么就要使用history模式,但是使用history模式还有一个问题就是,在访问二级页面的时候,做刷新操作,
会出现404错误,那么就需要和后端人配合让他配置一下apache或是nginx的url重定向,重定向到你的首页路由
上就ok啦。
hash —— 即地址栏 URL 中的 # 符号(此 hash 不是密码学里的散列运算)。比如这个 URL:
http://www.abc.com/#/hello,hash 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,
但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。history —— 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 
方法。(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、
go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,
但浏览器不会立即向后端发送请求。因此可以说,hash 模式和 history 模式都属于浏览器自身的特性,Vue-Router 只是利用了这两个特性
(通过调用浏览器提供的接口)来实现前端路由.


  • 输出以下值


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

console.log('1');

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})


// 1,7,6,8,2,4,3,5,9,11,10,12


  • 数组求第二大值及其位置

aa=[1,3,5,2,7,6]
aa[aa.indexOf(Math.max.apply(Math,aa))]=null
console.log(Math.max.apply(Math,aa), aa.indexOf(Math.max.apply(Math,aa)))

这里写图片描述

  • 冒泡排序与二分法排序

冒泡排序
依次比较相邻的两个值,如果后面的比前面的小,则将小的元素排到前面。依照这个规则进行多次并且递减的迭代,
直到顺序正确。时间复杂度,空间复杂度,稳定性平均时间复杂度O(n*n)最好情况O(n)最差情况O(n*n)空间复杂度O(1)稳定性:稳定var examplearr=[8,94,15,88,55,76,21,39];
function sortarr(arr){
    for(i=0;i<arr.length-1;i++){
        for(j=0;j<arr.length-1-i;j++){
            if(arr[j]>arr[j+1]){
                var temp=arr[j];
                arr[j]=arr[j+1];
                arr[j+1]=temp;
            }
        }
    }
    return arr;
}
sortarr(examplearr);
console.log(examplearr);


  • vue filter
  • vue-router
mode:
hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持
 HTML5 History Api 的浏览器。history: 依赖 HTML5 History API 和服务器配置。
查看 HTML5 History 模式。abstract: 支持所有 JavaScript 运行环境,如 Node.js 
服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式。

base

应用的基路径。例如,如果整个单页应用服务在 /app/ 下,
然后 base 就应该设为 "/app/"

linkActiveClass

全局配置 <router-link> 的默认“激活 class 类名”
默认值: "router-link-active"

linkExactActiveClass

默认值: "router-link-exact-active"全局配置 <router-link> 精确激活的默认的 class

scrollBehavior

parseQuery / stringifyQuery

提供自定义查询字符串的解析/反解析函数。覆盖默认行为

fallback

当浏览器不支持 history.pushState 控制路由是否应该回退到 hash 模式。默认值为 true。在 IE9 中,设置为 false 会使得每个 router-link 导航都触发整页刷新。它可用于工作在 IE9 
下的服务端渲染应用,因为一个 hash 模式的 URL 并不支持服务端渲染。


  • vuex的定义 

1)Vuex 是一个专门为 Vue.js 应用程序开发的状态管理模式,使用插件的形式引进项目中

2)集中存储和管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化

3)每一个 Vuex 应用的核心就是 store(仓库),new Vue.store({...}),“store”基本上就是一个
容器,它包含应用中大部分的状态 (state)
1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,
那么相应的组件也会相应地得到高效更新。

2)你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit)
 mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了
解我们的应用

  • vuex中的5个核心概念

state对象:(在computed中引入)Vuex 使用单一状态树——
用一个对象就包含了全部的应用层级状态;每个应用将仅仅包含一个
 store 实例


getters对象:(可以认为是store的计算属性),在组件中的computed
中引入

getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生
了改变才会被重新计算

Getter 接受 state 作为其第一个参数,也可以接受其他 getter
 作为第二个参数

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计
算属性

mutations对象:更改 Vuex 中 store 的状态的唯一方法是commit 
mutation;

mutation类似于事件,每个 mutation 都有一个字符串的 事件类型 
(type) 和 一个 回调函数 (handler);

回调函数对状态进行更改, state 作为第一个参数

actions类似mutations,不同之处

action 提交的是 mutation,mutation直接变更状态。
action 可以包含任意异步操作


Module:使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,
store 对象就有可能变得相当臃肿。Vuex 允许我们将 store 分割成模块(module)。
每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式
的分割

  • computed watch 区别

computed属性只在依赖的数据发生变化时,才会重新计算,否则当多次调用computed属性时,
调用的其实是缓存;而methods和watch则每调用一次就计算一次;以官方例子(获取全名)为例,computed的写法更加简洁,代码量更少;