① for...in for...of(es6引入)
-
for...in循环遍历key -
for...of循环遍历item,对象默认无法使用,因为没有部署Iterator遍历器接口。如果和Object.keys()搭配使用,即使不部署iterator接口也可以遍历。
② async await理解
- 引入
promise,是异步编程的一种方式,解决了ES6之前的回调地狱的问题。 -
async返回的是一个promise对象。 -
async函数中可以不包含await, 但是await必须在async函数中,await后面的表达式可以是promise,也可以是非promise,如果是promise,则返回值就是promise的resolve()的值,如果promise是rejecte(),那么需要使用try catch来捕获异常,如果是非promise值,返回值就是表达式的返回值。 -
async和await算是promise的语法糖,真正实现了没有回调函数获取到值。ps :then()也算是回调函数。
③ v-model 双向绑定原理
- 本质上是
v-bind和v-on的结合体 - 通过订阅发布结合
Object.defineProperty()实现双向绑定。-
Object.defineProperty()劫持了属性的get,set方法,一旦数据发生改变,则会通知订阅者发布更新(update),从而更新视图。
-
④ vue的通信方式
④ - ① 组件间通信的方式
- 父子组件通信
-
props(父 -> 子)$emit(子 -> 父) -
$parent$children, 访问父组件实例,或子组件实例 -
provide/ inject, 是vue2.2.0新增的api,父组件中配置了provide,子组件配置inject注入即可。(示例代码如下:C 是 B 的子组件,B 是 A 的子组件)
-
// A.vue
<template>
<div>
<comB></comB>
</div>
</template>
<script>
import comB from '../components/test/comB.vue'
export default {
name: "A",
provide: {
for: "demo"
},
components:{
comB
}
}
</script>
// B.vue
<template>
<div>
{{demo}}
<comC></comC>
</div>
</template>
<script>
import comC from '../components/test/comC.vue'
export default {
name: "B",
inject: ['for'],
data() {
return {
demo: this.for
}
},
components: {
comC
}
}
</script>
// C.vue
<template>
<div>
{{demo}}
</div>
</template>
<script>
export default {
name: "C",
inject: ['for'],
data() {
return {
demo: this.for
}
}
}
</script>
-
ref refs- 如果在普通的DOM元素上使用,则引用是DOM元素,如果是子组件使用,引用则是子组件的实例,可以通过实例直接调用组件方法或者访问组件数据。
-
EventBus不推荐使用,当项目过大时,难以维护 - VueX
- localStorage / sessionStorage
④ - ② 路由间传参
⑤ vue计算属性缓存原理?
⑥ 深拷贝浅拷贝
- 深浅拷贝一般发生在引用类型上面,普通数据类型永远都是深拷贝。当拷贝引用类型时,拷贝的仅仅是引用,内存中的地址值还是相同的。即改变拷贝后的数据,会对原数据发生影响。
- 修改副本数据影响原数据的是浅拷贝,不影响源数据的是深拷贝。
- 深拷贝的实现:
-
lodash函数库 - 递归实现、
-
JSON.parse(JSON.stringify())、如果对象中有function,undefined,regExp则会忽略 -
concat和slice也可以实现(仅对基本类型的数据生效)
-
⑦ 介绍一下http,https,为什么https比http更安全?
- http:超文本传输协议,以明文的形式传输内容,不提供任何加密。攻击者一旦获取到传输报文,就可以读取到报文信息
- https:安全套接字层超文本传输协议,在http的基础上添加了SSL协议,SSL依靠证书来验证服务器的身份,并未浏览器和服务器之间的通信加密。
https的原理
- 发送HTTPS请求,连接到server的433端口
- 在服务端配置数字证书
- 传送证书
- 客户端解析并验证证书的有效性
- 加密信息(用的是证书加密后的随机值,客户端和服务端的通信就可以进行加密了)
- 服务端解析加密信息
- 传输加密信息
- 客户端接收信息
https的优缺点
- 优点:安全,SEO(搜索排名靠前)
- 缺点:费用,SEO(页面加载变慢,功耗增大,并非绝对安全)
⑧ forEach 和 map 的区别
-
forEch没返回值,或者说返回值是undefined,直接在函数内操作循环项目。会改变原数组。 -
map返回一个操作后的数组,不会改变原数组。一般在函数内return
⑨ 垂直居中方式
- 定位
- flex布局
- grid布局
- vertical-align:middel (图片垂直居中)
- line-height: (文字图片垂直居中)
⑩ Tcp三次握手,四次挥手原理
⑪ 输出url到页面完成的整个过程?
- 查找缓存,看是否有缓存好的资源可以提高加载速度。
- DNS解析,将域名解析成IP地址。
- TCP三次握手(双方发包的过程)
- 发送HTTP请求
- 服务端处理HTTP请求,并返回响应报文
- 浏览器接受响应报文并解析,并且渲染
- 断开连接(TCP四次挥手)
关于第六步:
如果返回的是HTML页面,浏览器会将html解析成dom树,css解析成css规则树,结合dom树和规则树形成渲染树。根据渲染树中的每一个DOM节点计算出相应的位置后开始渲染。
⑫ 排序算法,冒泡排序?
- Array.prototype.sort(),使用的是快速排序。
冒泡排序(思路如下)
- 数组中有
n个数,比较相邻的的两个数,如果前者大于后者,就把两个数字交换位置。这样一来,第一轮就可以选出一个最大的数放在最后面;那么经过(n-1)轮,就完成了所有数的排序。
冒泡排序
// 冒泡排序写法
const arr = [1, 20, 10, 30, 22, 11, 55, 24, 31, 88, 12, 100, 50];
function swap(arr, i, j){
const temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
for(let i = 0; i < arr.length - 1; i++){
let flag = false;
for(let j = 0; j < arr.length - 1 - i; j++){
if(arr[j] > arr[j+1]){
swap(arr, j, j+1);
flag = true;
}
}
if(!flag){
break;
}
}
⑬ web安全性?
- xss攻击 :两大要素:攻击者提交恶意代码,浏览器执行恶意代码。解决方案:防止用户注入恶意代码。
- csrf攻击 : 使用cookie冒充用户发送请求,导致目标网站错误响应
- dns劫持 : dns涉嫌违法,较少
- http劫持 : 使用https
⑭ 变量提升?
- var会变量提升
- function 声明也会函数提升
⑮ Node.js理解?文件读写?
- 理解 : 既是开发平台,也是运行环境。基于v8引擎开发的,所以编程时使用javascript,可以理解为 让js在服务器上运行的平台。
- 文件读写: 引入
require('fs')模块,fs.writeFile() 、 fs.readFile()
⑯ 手写Map方法
- 第一个参数是函数,第二个参数可指定函数中的this
Array.prototype._map = function(fn,thisValue){
// 赋值数组给arr
let arr = thisValue || this
// 声明一个空数组,作为将要返回的结果
let result = []
// 判断第一个参数是否为函数
if(typeof fn !== 'function'){
throw new Error(fn + '该参数必须要为函数')
}
// 进行循环并且将执行结果返回
for (let i = 0; i < arr.length ; i ++){
let r = fn.call(arr , arr[i] , i , arr)
result.push(r)
}
return result
}
let myMapVal = [1,2,8,6]._map((item)=>{
return item * 2
})
console.log(myMapVal) // [2, 4, 16, 12]
⑰ 箭头函数与普通函数的区别?
- 箭头函数写法更为简洁
- 箭头函数内部没有
this,箭头函数中的this执行编写时的环境。 -
call、apply、bind无法改变this的指向 - 箭头函数继承而来的
this,指向永远不会改变 - 构造函数不能使用箭头函数
- 箭头函数没有自己的
arguments - 箭头函数没有原型
prototype - 箭头函数不能用作
Generator函数,不能使用yeild关键字
⑱ 何时用Object,何时用Map
- 当我们只需要用到一个简单,便于操作的键值对数据结构时,用Map更具有优势。因为Map具有各种操作数据的方法,
get set has delete等。但是Object始终是基石,因为JSON是直接支持转换为Object的,JSON暂未支持Map结构。
⑲ 原型链理解
- 当访问实例对象的属性或者方法时,首先会在自身查找看是否有定义,如果没有就去
__proto__属性查找,一直到原型链的顶端(null),因为Object.proto为null,如果还没有则报错(属性是输出undefined,函数是xxx is not a function)。 - 首先说原型 、 再说原型与实例的关系。
⑳ new 关键字背后所做的事情
-
new执行的构造函数,函数内部默认生成了一个对象。 - 函数内部的
this,指向新生成的对象。 -
new执行后生成的对象,默认是该构造函数的返回值。
㉑ 介绍一下 Set 和 Map 结构
Set
- 类似于数组,只不过该结构内的成员是不重复的。比数组丰富的操作方法,如
add,delete,has,clear, 属性:size - 遍历方法(注意:set结构没有key,或者说key和value是同一个值)
- Set.prototype.keys() 遍历键名
- Set.prototype.values() 遍历键值
- Set.prototype.entries() 遍历键值对
- Set.prototype.forEach(()=>{}) 使用回调函数的方法遍历
weakSet
- 使用
new weakSet(), 参数只能是数组,数组中成员必须是对象。
Map
- 类似于对象,有比对象丰富的操作方法,如
add,get,set,delete,has,属性:size - 遍历方法
- Set.prototype.keys() 遍历键名
- Set.prototype.values() 遍历键值
- Set.prototype.entries() 遍历键值对
- Set.prototype.forEach(()=>{}) 使用回调函数的方法遍历
⑳㉑㉒㉓㉔㉕㉖㉗㉘㉙㉚㉛㉜㉝㉞㉟㊱㊲㊳㊴㊵㊶㊷㊸㊹㊺㊻㊼㊽㊾㊿