基础相关
es6新增了哪些新特性,较之前有什么变化
- let变量,主要用于取代var
- 阻止变量提升
console.log(a) // undefined
console.log(b) // Uncaught ReferenceError: Cannot access 'b' before initialization
var a
let b
- 不可重复定义
let b = 2 // Uncaught SyntaxError: Identifier 'b' has already been declared
- 只在块级作用域内有效
{
let a = 1;
{
let a = 2;
console.log(a); // 2
}
console.log(a) // 1
}
- const常量,一旦声明不可改变
const c = 1
c = 2 // Uncaught TypeError: Assignment to constant variable.
- 基本数据类型symbol,Symbol()函数会返回symbol类型的值
- 每个从Symbol()返回的symbol值都是唯一的
Symbol("foo") === Symbol("foo"); // false
- 解构赋值
- 数组解构
let foo = [1, 3, 5, 7, 9];
const [a, b, c, ...rest] = foo;
console.log(a); // 1
console.log(b); // 3
console.log(c); // 5
console.log(rest); // [7, 9]
// 剩余参数一定是要放在最后,否则报错
// const [a, ...rest, b, c] = foo;
// Uncaught SyntaxError: Rest element must be last element
- 默认值
let a, b;
[a=1, b=2] = [3];
console.log(a); // 3
console.log(b); // 2
- 交换
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a); // 2
console.log(b); // 1
- 对象解构,基本类似(键名需要保持一致)
let {a, b} = { a: 1, b: 2 }
- 模板字符串
let x = 110;
console.log(`请求呼叫${x}`);
- 箭头函数
- 仅有一个参数时,可省略括号
const fn = param => {
// ...
}
- 函数体直接return一个结果,可省略 {}
const fn(a, b) => a + b;
了解防抖节流吗,什么场景下会用到
- 防抖
- 在给定的n秒内再次触发,将会重新计时,到达n秒才执行函数
- 搜索优化,停止输入达到n秒再执行检索
- window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发一次
function debounce(fn, wait) {
let timeout;
return function(...args) {
if(timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
fn.apply(this, args);
}, wait);
}
}
- 节流
- 就是指连续触发事件但是在 n 秒中只执行一次函数
- 转盘抽奖,鼠标或手指持续触发的情况下
- 监听滚动事件,比如是否滑到底部自动加载更多
function throttle(fn, wait) {
let previous = 0;
return function(...args) {
let now = Date.now();
if (now - previous > wait) {
fn.apply(this, args);
previous = now;
}
}
}
移动端适配,有哪几种方式
- rem,是基于根元素html计算的单位,1rem基本大小为16px
html {
font-size: 2rem; // 32px
div {
font-size: 2rem; // 64px, 看到区别了吧
}
}
- em,是基于父元素计算的单位
<div class="fir">
<div class="sec">
收到了3份offer
<p class="thir">收到了3份offer</p>
</div>
</div>
<style>
.fir {
font-size: 20px;
}
.sec {
font-size: 2em;
}
.thir {
font-size: 2em;
}
</style>
- postcss-px-to-viewport(本人一般用这个插件)
// 安装
npm i postcss-px-to-viewport --save-dev
// vue.config.js中配置
module.exports = {
// ...
"postcss-px-to-viewport": {
unitToConvert: "px", // 默认值`px`,需要转换的单位
viewportWidth: 375, // 视窗的宽度,对应设计稿宽度
viewportHeight: 667, // 视窗的高度, 根据375设备的宽度来指定,一般是667,也可不配置
unitPrecision: 3, // 指定`px`转换为视窗单位值的小数位数
propList: ["*"], // 转化为vw的属性列表
viewportUnit: "vw", // 指定需要转换成视窗单位
fontViewportUnit: "vw", // 字体使用的视窗单位
selectorBlaskList: [".ignore-"], // 指定不需要转换为视窗单位的类
mediaQuery: false, // 允许在媒体查询中转换`px`
minPixelValue: 1, // 小于或等于`1px`时不转换为视窗单位
replace: true, // 是否直接更换属性值而不添加备用属性
exclude: [], // 忽略某些文件夹下的文件或特定文件
landscape: false, // 是否添加根据landscapeWidth生成的媒体查询条件 @media (orientation: landscape)
landscapeUnit: "vw", // 横屏时使用的单位
landscapeWidth: 1134 // 横屏时使用的视窗宽度
}
};
如何实现垂直水平居中
div
width 100px
height 100px
position fixed
top calc(50% - w/2)
left calc(50% - h/2)
布局相关(太多,此处不展开)
- float属性
- flex
有做过两个独立的项目间,更新对方页面吗
木有
- window.postMessage结合iframe可以实现
// test.html
<iframe src="http://192.168.xxx.xxx:8080/"></iframe>
let array= ['打工人', '打工魂', '打工都是人上人', '奥利给'];
window.onload = function() {
window.frames[0].postMessage(array, '*');
}
// test.vue
mounted() {
window.addEventListener('message', function(e) {
console.log(e.data, '------fromOtherProj')
})
}
深拷贝怎么实现
- 主要就是递归遍历自身
function deepClone(source) {
let objClone = Array.isArray(source) ? [] : {};
if (source && typeof source === 'object') {
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (typeof source[key] === 'object') {
objClone[key] = deepClone(source[key]);
} else {
objClone[key] = source[key]
}
}
}
}
return objClone;
}
求一个元素在数组中出现的次数
- 当时用的比较菜的方式,然后面试官要求改进时间复杂度为O(1),不能用for循环了(这我还没研究,有路过的可以指点下)
function getLength(array, x) {
let tmp = []
array.forEach(element => {
if (element === x) {
tmp.push(element)
}
});
return tmp.length;
}
了解有哪些前端攻击吗
- 之前小公司经历过一个xss跨站脚本攻击(收到非法图片url)
- 主要原因是过分信任客户端传输信息,导致有恶意传输脚本(常见iframe,script标签)变成了程序可执行的一部分,可能导致账户信息、劫持回话、弹框登录(恶意引导至非法页面)、改变内容欺骗用户等后果
- 避免xss攻击也简单,前端进行表单验证,格式校验,服务端给用户增加token,前端登录时携带token,post请求取代get请求
js中类的继承是怎么实现的
- 根据《你不知道的JavaScript》系列讲述,js中其实没有类的概念,‘类’的继承是基于原型(prototype)委托
讲讲原型和原型链吧
- 原型
- 对象的原型就是其构造函数的
prototype
- 引用类型有一个
__proto__
属性,称之为隐式原型,该属性又指向其构造函数的prototype
- 原型链
- 原型链不是一个结构的概念
- 是在查找对象属性的时候,当前对象本身没有找到,就会先去到它的隐式原型(
person1.__proto__
)上查找,对应其构造函数的原型(Person.prototype
),还没有找到就会继续向上,Person.prototype.__proto__
,对应其构造函数的原型(Object.prototype
),如果还没找到,直到Object.prototype.__proto__
(指向null) - 这样一层一层查找的过程,称为原型链
instanceof实现
- instanceof是基于原型,只能用来判断引用类型
function instanceof(obj, type) {
if(typeof obj !== 'object' || obj === null) return false;
let proto = obj.__proto__;
let prototype = type.prototype;
while(true) {
if(proto === null) return false;
if(proto === prototype) return true;
proto = proto.__proto__;
}
}
vue相关
如何实现v-model双向绑定
- 父组件
<template>
<div>
<p>{{ value }}</p>
<son v-model="value" />
</div>
</template>
<script>
import son from './son.vue'
export default {
data() {
return {
value: '',
};
}
components: {
son
}
};
</script>
- 子组件
<template>
<div>
<input :value="value" @input="onInput" />
</div>
</template>
<script>
export default {
model: { // 如果不使用model属性,$emit('input', xxx)也是一样的
prop: 'value',
event: 'change'
},
props: {
value: {
type: String,
default() {
return ''
}
}
},
methods: {
onInput(e) {
this.$emit('change', e.target.value)
}
}
};
</script>
vue是如何实现双向绑定的
- vue2.x版本是基于Object.defineProperty(),通过其内部set和get方法,对数据进行劫持
- vue3.0是基于Proxy()来实现的
vue页面优化
- v-if和v-show区分场景使用
- 频繁切换,则需要提前渲染好,控制display显隐即可,适用v-show
- 不涉及频繁切换,则可以以使用v-if
- v-for遍历,加 :key="xxx",提高性能(diff算法进行父子节点更新的时候基于该key)
- 针对纯展示列表,axios请求过后进行this.list = Object.freeze(data),冻结对象,禁止双向绑定修改对象,减少一定的性能消耗
- 使用vant等UI库,使用babel-plugin-import、babel-plugin-component等插件按需引入,而不是使用全部引入,减少包体积
- 大量图片使用vue-lazyload懒加载等插件
- 路由懒加载,也是常规习惯
- 骨架/呼吸屏,提升用户体验
- SSR服务端渲染,相当于服务端直接返回html页面,提升首屏加载速度
- 架构层面,前端微服务,之前公司使用docker+caas平台,特别对于APP内嵌的情况,分模块各自部署在独立的微服务,减轻服务器压力,同时可以无感更新,提升用户体验
组件通讯都有哪些方式
- 父子组件通讯
- 父向子:父组件中给子组件标签v-bind绑定属性,子组件props接收
- 子向父:父组件中给子组件标签绑定事件(订阅事件),子组件
$emit('xxx', params)
(发布事件) provide、inject
$parent、$children
- eventBus总线机制,可跨组件级别,兄弟组件,爷俩组件都ok的
- Vue.observable()对象,简版的状态管理,创建之后,可随处更改state中的变量,也可随处获取state变量
- vuex核心插件,state,getters,mutations,actions4大属性,同时可做module拆分,mutations是同步提交,actions可异步提交多个dispatch到mutations
vue-router和vuex项目中怎么封装使用的
- 本人博客哈
用过react吗,vue和react的相似和区别之处
木有
- 相似
- virtual dom,简单说就是用js对象格式来描述dom
- 组件化思想
- props子组件向父组件传值
- 脚手架,vue-cli和Create React App
- 配套核心插件,vuex,vue-router 和 react-redux,react-router
- 区别
- vue是双向绑定,react是单向数据流
- vue默认是模板语法(也支持render和JSX语法),react默认是JSX(JavaScript和xml语法混合着写)
写在最后
- 面试的时候会的好好说,要有条理,不知道的更要理直气壮,这个说不好不会,就行了
- 别怕打击,被嫌弃太菜,下一家接着面,毕竟各位都是仌
- 每场面试都是一次学习机会,也是对自己技术的检验,珍惜