个人前端面试题目总结
- 个人前端面试题目总结(未工作)
个人前端面试题目总结(未工作)
形式:电话面试
面试内容不完全记录:
关于React
关于Vue
*1.vue中数据双向绑定的原理
vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的。
vue是通过Object.defineProperty()
来实现数据劫持的。Object.defineProperty()
可以来控制一个对象属性的一些特有操作,比如读写权、是否可以枚举。其中的一些方法还可以对数据的一些特定操作实现监听,比如set()
方法可以在给数据赋值的时候执行,get()
方法可以在获取数据值的时候执行。
例如:在平常获取到对象的值:
var Book = {
name: 'vue权威指南'
};
console.log(Book.name); // 在控制台会打印出 vue权威指南
但是怎么在获取到name属性值的时候加上一个《》呢?
var Book = {}
var name = '';
Object.defineProperty(Book, 'name', {
set: function (value) {
name = value;
console.log('你取了一个书名叫做' + value);
},
get: function () {
return '《' + name + '》'
}
})
Book.name = 'vue权威指南'; // 你取了一个书名叫做vue权威指南
console.log(Book.name); // 《vue权威指南》
通过
Object.defineProperty( )
设置了对象Book的name属性,对其get和set进行重写操作,顾名思义,get就是在读取name属性这个值触发的函数,set就是在设置name属性这个值触发的函数,所以当执行 Book.name = ‘vue权威指南’ 这个语句时,控制台会打印出 “你取了一个书名叫做vue权威指南”,紧接着,当读取这个属性时,就会输出 “《vue权威指南》”,因为我们在get函数里面对该值做了加工了。
*2.vue中的MVVM模式
MVVM是 Model-View-ViewModel 的缩写。其中,
- M:
Model
,模型层,主要负责数据的处理。 - V:
View
,视图层,主要负责数据的渲染。 - VM:
ViewModel
,是Model和View之间联系的桥梁,是实现双向绑定的要点。
ViewModel
中的DOM Listeners和Data Bindings
ES6中有哪些新特性
1.const,let
两者都为块级作用域。let表示声明变量,而const表示声明常量。
2.模板字符串(字符串的拼接)
在ES6之前,字符串之间的拼接用的是**+或者concat()方法**,ES6中可以使用模板字符串来进行拼接:
// 模板字符串采用的符号是:倒引号``以及${}
a='Hello World'
${a}
3.箭头函数
箭头函数就相当于是个匿名函数,它的出现主要是为了解决this指向的问题。并且省略了function关键字和return关键字。
// ES5
var add = function (a, b) {
return a + b;
};
// 使用箭头函数
var add = (a, b) => a + b;
// ES5
[1,2,3].map((function(x){
return x + 1;
}).bind(this));
// 使用箭头函数
[1,2,3].map(x => x + 1);
当你的函数有且仅有一个参数的时候,是可以省略掉括号的。当你函数返回有且仅有一个表达式的时候可以省略**{} 和 return**。
4.函数参数的默认值
// 之前定义函数的默认值
function printText(text) {
text = text || 'default';
console.log(text);
}
// ES6;
function printText(text = 'default') {
console.log(text);
}
printText('hello'); // hello
printText();// default
5....Rest操作符
…Rest操作符通常用于函数传递参数时候获取多个参数构成的集合,也就是获取剩余的几个全部参数。
6.二进制和八进制字面量
ES6 支持二进制和八进制的字面量,通过在数字前面添加 0o 或者0O 即可将其转换为八进制值:
let oValue = 0o10;
console.log(oValue); // 8
let bValue = 0b10; // 二进制使用 `0b` 或者 `0B`
console.log(bValue); // 2
7.解构赋值(对象,数组)
// 对象
const student = {
name: 'Sam',
age: 22,
sex: '男'
}
// 数组
// const student = ['Sam', 22, '男'];
// ES5;
const name = student.name;
const age = student.age;
const sex = student.sex;
console.log(name + ' --- ' + age + ' --- ' + sex);
// ES6
const { name, age, sex } = student;
console.log(name + ' --- ' + age + ' --- ' + sex);
8.对象超类
ES6 允许在对象中使用 super 方法:
var parent = {
foo() {
console.log("Hello from the Parent");
}
}
var child = {
foo() {
super.foo();
console.log("Hello from the Child");
}
}
Object.setPrototypeOf(child, parent);
child.foo();
// Hello from the Parent
// Hello from the Child
9.for…of 和 for…in
for…of 用于遍历一个迭代器,如数组:
let letters = ['a', 'b', 'c'];
letters.size = 3;
for (let letter of letters) {
console.log(letter);
}
// 结果: a, b, c
for…in 用来遍历对象中的属性:
let stus = ["Sam", "22", "男"];
for (let stu in stus) {
console.log(stus[stu]);
}
// 结果: Sam, 22, 男
10.Promise
从语法上讲,Promise 是一个对象,它可以获取异步操作的结果。Promise对象, 可以将异步操作以同步的流程表达出来。
箭头函数的主要作用
箭头函数就相当于是个匿名函数,它的出现主要是为了解决this指向的问题。
Promise的用法和作用
从语法上讲,Promise 是一个对象,它可以获取异步操作的结果。Promise对象, 可以将异步操作以同步的流程表达出来。
回调地狱:例如现在需要发送三个不同的请求
第一个正常发送
第二个请求需要第一个请求的结果中的某一个值作为参数
第三个请求需要第二个请求的结果中的某一个值作为参数
当请求数量一多就会出现回调嵌套的情况。
用法:
var p = new Promise(function(resolve, reject) {
if (){
// 异步请求加载成功后的回调函数,value就是异步操作的结果,作为参数传递出去,例如请求接口成功后获取到的返回数据。
resolve(value);
} else {
// 异步请求加载失败后的回调函数,error就是异步操作报出的错误,作为参数传递出去。
reject(error);
}
});
// 解析Promise对象并获取到对应的数据
promise.then(res=> {
// 从 resolve 获取正常结果
console.log(res);
}).catch(error=> {
// 从 reject 获取异常结果
console.log(error);
}).then(...) // 第二个then 是第一个then结束后的回调函数
Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。分别代表了异步请求成功和失败后的回调函数。
React和Vue的区别
区别
1.Vue提供了一系列的api(v-if,v-else,v-model), 而React的api 很少。
2.Vue的思想是响应式,数据可以实现双向绑定。React的思想是函数式,而且数据属于单向数据流。
3.vue 采用了template, react采用了jsx(本质上都是模版)。
相似之处
1.两者都采用组件化的开发方式。组件化就是将整个页面划分成一个一个的组件,组件之间通过某种方式相互联系,进行数据的传输。
2.都有相对应的构建工具,比如react采用的构建工具是create-react-app,vue的构建工具是vue-cli。
3.都是用于构建页面的基于js的框架。
Vue的优势
1.简单,容易上手。
2.语法性更强,能更加方便地操作DOM 元素。
Vue的劣势
1.性能不如react,不太适合大型项目
React的优势
1.基于虚拟DOM,兼容性好而且性能好。
2.语法性更强,能更加方便地操作DOM元素。
3.基于组件化地开发,更方便前端页面的搭建。
React的劣势
1.仅仅是一个前端UI组件库,不适合单独作为一个完整的框架,往往需要配合另外多种第三方库的使用。
2.上手难度相比于Vue更大。
css3有哪些新特性
比较常见和常用的特性:
圆角边框border-radius,边框阴影box-shadow,背景图片大小background-size,文本换行text-wrap,转换transform,样式转换transition,css动画**@keyframes**
什么是虚拟DOM
虚拟DOM,DOM树的虚拟表现。它是基于一个概念:改变真实的DOM状态比改变一个JavaScript对象花销要大很多而产生的。
Virtual DOM是一个映射真实DOM的JavaScript对象,如果需要改变任何元素的状态,那么是先在Virtual DOM上进项改变,而不是直接改变真实的DOM。当有变化产生时,一个新的Virtual DOM对象会被创建并计算新旧Virtual DOM之间的差别。之后这些差别会应用在真实的DOM上。
例如:
<ul class="list">
<li>item 1</li>
<li>item 2</li>
</ul>
上面这段html代码就相当于真实DOM,对应的虚拟DOM就是类似这样:
{
type: 'ul',
props: {'class': 'list'},
children: [
{ type: 'li', props: {}, children: ['item 1'] },
{ type: 'li', props: {}, children: ['item 2'] }
]
}
css垂直居中有哪些方法
利用相对定位,绝对定位+transform属性实现垂直居中,或者正居中
设置行高line-height
设置上下内边距padding
设置表格容器
将容器设置为display:table
,然后将子元素也就是要垂直居中显示的元素设置为display:table-cell
,然后加上vertical-align:middle
来实现。
flex布局(遇事不决,就用flex布局,解决99%问题)
css水平居中有哪些方法
margin: 0 auto;(给子元素)
父元素容器设置text-align: center;
浮动居中position: relative;float: left;left: 50%;
利用相对定位,绝对定位+transform实现水平居中
利用css的fit-content(给父元素)
.box {
width: fit-content;
margin: 0 auto;
}
flex布局(遇事不决,就用flex布局,解决99%问题)
怎么解决margin在垂直方向的时候像素重叠的问题
网页布局的三种常见形式:普通流,浮动,绝对定位。
普通流就是页面上的各个元素按照顺序自上而下地布局,其中行内元素会水平排列直到整行布满,块级元素会独占一行。
浮动就是在普通流的基础上尽可能地向左或者向右浮动。
绝对定位的元素不会对普通流的内容造成干扰。
问题描述:
在页面上有两个div,同时给这两个div设置margin为100px,按照理论情况,这两个元素的上下间距应该为100px+100px=200px,但是实际中的间距只有100px:
.box {
width: 100px;
height: 100px;
background-color: blue;
border-radius: 8px;
margin: 100px;
}
这不是一个Bug,这是一个规范。块的上外边距margin-top和块的下外边距margin-bottom会合并为单个边距。这就是外边距重叠的问题,解决方法就是用BFC容器:将两个div放置在不同的BFC中,这样的话两个BFC中的内容就不会互相干扰。所谓BFC就相当于是页面上的一块渲染区域,也可以看成是元素的一个属性。当某个元素拥有了BFC"属性"之后,这个元素可以看做一个隔离了的独立容器。容器里面的元素不会影响到外面的元素。
触发BFC的条件:
.container {
overflow: hidden;
}
<div class="container">
<div class="box"></div>
</div>
<div class="container">
<div class="box"></div>
</div>
BFC还有其他作用是:清除浮动(给父元素设置overflow: hidden;),阻止元素被浮动元素覆盖(给想要去除覆盖的元素设置overflow: hidden;)。
Vue的生命周期
Vue是基于组件化开发的框架,每个组件都有一个属于它的生命周期,从一个组件创建、数据初始化、挂载、更新、销毁,这就是一个组件所谓的生命周期。在组件中具体的方法有:
beforeCreate()
created()
beforeMount()
mounted()
beforeUpdate()
updated()
beforeDestroy()
destroyed()
Vue父子组件怎么传值
父组件传子组件
在父组件中引用子组件,将传的值直接写在标签内部,通过属性进行传值:
<Child message="Hello" />
在子组件中通过 props 进行接收值:
...
<script>
export default {
props:['msg'],
data:function(){
return {
}
}
}
</script>
...
子组件传父组件
当子组件给父组件进行传值的时候,要在子组件标签内定义自定义方法 。在子组件内通过 this.$emit ( ) 触发这个方法;,参数1 是自定义的方法名称,参数2 是需要传递的参数:
<button @click="handleClick">我要向父组件传值</button>
...
handleClick(){
this.$emit('sendInfo','第二个参数写你要传递的内容')
}
父组件中在子组件标签内自定义一个接收方法获取到传过来的值:
<template>
<div id="box">
我是父组件
<p>我是接收的子组件传过来的值:{{info}}</p>
<Child @sendInfo="getInfo"/>
</div>
</template>
<script>
import Child from './child';
export default {
data:function(){
return {
info:""
}
},
methods:{
getInfo(msg){
this.info = msg;
}
},
components:{
Child
}
}
</script>
map和forEach的区别
forEach没有返回值,仅仅用于处理逻辑。
map有返回值,可以return出来,常用于页面上的列表渲染。
CSS清除浮动
<div class="outer">
<div class="div1">1</div>
<div class="div2">2</div>
<div class="div3">3</div>
</div>
.outer{border: 1px solid #ccc;background: #fc9;color: #fff;}
.div1{width: 80px;height: 80px;background: red;float: left;}
.div2{width: 80px;height: 80px;background: blue;float: left;}
.div3{width: 80px;height: 80px;background: sienna;float: left;}
当三个子元素的float都设置成left
(浮动)之后,父元素的高度会被挤成一条线。三个子元素div不能被完整包裹在父元素中。背景不能显示,边框不能撑开。
清除浮动的方法
1.添加新标签,并设置clear:both
样式
<div class="outer">
<div class="div1">1</div>
<div class="div2">2</div>
<div class="div3">3</div>
<div class="clear"></div>
</div>
.clear{clear:both; height: 0; line-height: 0; font-size: 0}
效果:此时三个子元素div全部被父元素包裹住,并且所有属性都恢复正常。
2.父元素增加overflow: auto
样式
<div class="outer over-flow"> //这里添加了一个class
<div class="div1">1</div>
<div class="div2">2</div>
<div class="div3">3</div>
</div>
.over-flow{
overflow: auto;
zoom: 1; //zoom: 1; 是在处理兼容性问题
}
实现效果和第一种方法中的一样。
3.给父元素添加伪类元素
.outer::after {
clear:both;
content:'.';
display:block;
width: 0;
height: 0;
visibility:hidden;
}
详细介绍一下css盒模型
有两种盒子模型:IE盒模型(border-box)、W3C标准盒模型(content-box)。
一般盒模型分为:内容(content)、填充(padding)、边界(margin)、边框(border)四个部分。
W3C标准盒模型和IE盒模型的区别:
W3C标准盒模型中,盒模型的宽度width和高度height仅仅包括内容content,不包括边框border和内边距padding。
而在IE盒模型中,盒模型的宽度width和高度height包括内容content,边框border和内边距padding。
js有哪些基本数据类型,有哪些其它数据类型
js 一共有六种基本数据类型,分别是 Undefined、Null、Boolean、Number、String、NaN,还有在 ES6 中新增的 Symbol 和 ES10 中新增的 BigInt 类型。
Symbol 代表创建后独一无二且不可变的数据类型,它的出现我认为主要是为了解决可能出现的全局变量冲突的问题。
BigInt是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。
基本数据类型和引用数据类型的区别是:存储位置不同。
原始数据类型直接存储在栈中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储。
引用数据类型存储在堆中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
js中如何对一个数组进行增删改查的操作
创建一个数组:
// 字面量方式:
var a = [3, 11, 8]; // [3,11,8];
// 构造器:
// 实际上 new Array === Array,加不加new 一点影响都没有。
var a = Array(); // []
var a = Array(3); // [undefined,undefined,undefined]
var a = Array(3,11,8); // [ 3,11,8 ]
向数组中增加元素
// 向数组的开头添加一个或更多元素
unshift()
// 向数组的末尾增加一个或多个元素
push()
//向数组中间位置添加一个或多个元素
splice()
// concat()两个数组拼接
concat()
在数组中删除元素
// js中数组有一个新特性就是length属性不仅仅是只读的,因此可以直接修改属性来从数组中删除末尾的若干个元素
var list = [1,2,3]
list.length = 2
console.log(list) // 输出[1,2]
// delete()方法
var arr = [1, 2, 3, 4]
delete arr[0] //delete删除元素,但是原数组的长度不会变化
console.log(arr[0]) // 输出undefined
console.log(arr.length) // 输出4
// pop()方法
pop() 可以从原数组中取出末尾的一个元素,相当于从原数组中删除了最后一个元素
// shift()方法
shift() 可以从原数组中取出头部的一个元素,相当于从原数组中删除了第一个元素
// splice()方法
list.splice(开始删除的位置, 删除的元素个数)
// forEach()方法或者filter()过滤器
通过循环的方法也可以实现从数组中删除掉某一个或几个元素
在数组中修改元素
// 直接通过下标修改
var arr = [1, 2, 3, 4]
arr[1] = 6
// splice()方法
var arr = [1,2,3,4,5];
arr.splice(2, 1, 10);
console.log(arr); //[1, 2, 10, 4, 5]
在数组中查找元素
// indexOf()方法:查找指定元素的下标(索引值)
// indexOf(要查找的值,查找开始的位置)
// 如果查找不到就会返回-1
var arr = [1,2,3,4,5,2];
var index = arr.indexOf(2);
console.log(index); // 1
index = arr.indexOf(2, 0);
console.log(index); // 1
index = arr.indexOf(2, 2);
console.log(index); // 5
index = arr.indexOf(6);
console.log(index); // -1
数组倒序
// reverse()方法
var arr = [1,2,3,4,5,2];
console.log(arr.reverse()); // [2, 5, 4, 3, 2, 1]
console.log(arr); // [2, 5, 4, 3, 2, 1]
如果让你设计一个页面的交互,你会怎么设计
个人理解:首先页面交互设计的最重要的就是突出重点,要让用户清楚的知道做这个交互的目的是什么(例如提醒用户保证输入框内的内容不为空),其次页面交互要做到简洁,高效,不能太复杂,太复杂的页面交互会降低用户的体验感受。
关于CSS
flex布局
Flex是FlexibleBox的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。
任何一个容器都可以指定为Flex布局。行内元素也可以使用Flex布局。注意,设为Flex布局以后,子元素的float、cl
ear和vertical-align属性将失效。
采用Flex布局的元素,称为Flex容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为Flex
项目(flex item),简称"项目"。
容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis),项目默认沿主轴排列。
以下6个属性设置在容器上。
flex-direction
属性决定主轴的方向(即项目的排列方向)。
flex-wrap
属性定义,如果一条轴线排不下,如何换行。
flex-flow
属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。
justify-content
属性定义了项目在主轴上的对齐方式。
align-items
属性定义项目在交叉轴上如何对齐。
align-content
属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
以下6个属性设置在项目上。
order
属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
flex-grow
属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
flex-shrink
属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
flex-basis
属性定义了在分配多余空间之前,项目占据的主轴空间。浏览器根据这个属性,计算主轴是否有多余空间。它的默认
值为auto,即项目的本来大小。
flex属性是flex-grow,flex-shrink和flex-basis的简写,默认值为0 1 auto。
align-self
属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父
元素的align-items属性,如果没有父元素,则等同于stretch。
关于微信小程序
v-if和v-show的区别,使用时机
区别:v-if是通过控制dom节点的存在与否来控制元素的显隐;v-show是通过设置DOM元素的display样式,block为显示,none为隐藏;
使用时机:如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。