1. vue、react异同点
比较:
1、vue使用的则是html一个简答的扩展,基础语法没有变化,jsx是基于xhtml的js,而且是可以再jsx中写HTML的,
2、React中没有指令的概念,vue中的指令相比较就非常多,也很实用:v-if,v-model,v-show,v-for,v-on....
3、React想是想数据的双向绑定是要借助setData()方法的,但是Vue只需借助data()就可以了,相对React也更简单
相同点:
都是虚拟dom,二者都有很多生命周期中的钩子函数,二者都鼓励组件化开发SPA应用,父子组件传递数据也都是用props,子向父就要通过函数来传递,二者也都能构建自己的工具。
2. eventLoop原理
为了确保 异步代码 可以在 同步代码 执行后继续执行 (timeout)
3. 防抖和节流
防抖和节流是针对响应跟不上触发频率这类问题的两种解决方案
防抖(设定timeout,函数设定的时间后执行)
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);
}
}
}
节流(设定时间间隔,按间隔时间循环执行)
function throttle(func, wait ,type) {
if(type===1){
let previous = 0;
}else if(type===2){
let timeout;
}
return function() {
let context = this;
let args = arguments;
if(type===1){
let now = Date.now();
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}else if(type===2){
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
}
4. 水平垂直居中的多种方式
1、position 元素已知宽度
2、position transform 元素未知宽度
3、flex布局
4、table-cell布局
5. promise、generator、async、await怎么使用,有什么区别
1、promise是一种新的写法,用来解决“回调地狱”的问题
//使用同步的写法,解决异步操作,。(异步-性能高,用户体验更好;同步-更简单,更方便)
//使用方法:
let pro = new Promise((reslove,reject)=>{
$.ajax({
url:'1.txt',//1.txt文件中返回json {"a":12,"b":5}
dataType:'json',
success(json){
reslove(json)//成功会调用reslove函数
},
error(err){
reject(err) //失败调用reject函数
}
})
})
//调用方法:(当pro内部函数执行完成之后,就会调用then方法。then方法取代了AJAX中原本的成功与失败方法。)
pro.then((json)=>{
alert("成功")
},
(err)=>{
alert("失败")
})
//使用then()方法调用promise,参数为两个函数,第一个函数为成功,第二个函数为失败
//调用方法(多次调用):
Promise.all([pro,pro1,pro2]).then((arr)=>{
alert("成功");
let[a,a1,a2]=arr;
},
(err)=>{
alert("失败")
})//pro\pro1\pro2是三个Promise对象。
//使用all()之后 需要参数对象内部函数全部执行完毕之后,才执行then,成功后返回一个数组,可以用解构赋值来接收为独立的数据。
//当多个pro对象,有逻辑关系的情况下。需要使用async、await解决。
//Promise.race()与Promise.all()的区别是,race()是 参数中ajax只要有一个完成即算完成。all()需要参数所有的ajax全部完成才执行成功
//注:JQ中ajax的返回值就是一个Promise对象。所以ajax也有then方法,用来执行成功与失败。所以Promise.all()中的参数,可以直接放ajax。
//Promise.all([$.ajax(xxx),$.ajax(xxx),$.ajax(xxx)]).then()//正常执行成功失败的方法。arr为三个ajax的返回数据。
2、generator 函数 (生成器函数)
Generator是协程在ES6的实现,最大的特点就是可以交出函数的执行权,懂得退让。
var fetch = require('node-fetch');
function* gen(){
var url = 'https://api.github.com/users/github';
var result = yield fetch(url);
console.log(result.bio);
}
var g = gen();
var result = g.next();
result.value.then( data => return data.json).then (data => g.next(data))
3、Async/await:其实async函数就是Generator函数的语法糖
async用于声明一个function是异步的,await用于等待一个异步方法执行完成
//只要在函数前加上async即可 表明这是一个async函数。函数体中使用await代替yield。//调用直接运行函数名即可;
async function show(){}
//await 会判断返回的数据对象,如果不是一个异步操作他就不会停止,例如 await 12;就会直接运行不会出现暂停。
//await 后可以放promise、generator函数,或者另外一个async函数
//async 后的function可以省略,匿名函数 async ()=>{}
async function show(){
let data = await $ajax(xxx);
let data1 = await $ajax(xxx);
let data2 = await $ajax(xxx);
console.log(data,data1,data2)
}
show()//data,data1,data2 的数据
//含有逻辑关系的异步
async function show(){
let data = await $ajax(xxx);
if(dataxxxx){//如果满足条件走data1
let data1 = await $ajax(xxx);
console.log(data1)
}else{//否则走data2
let data2 = await $ajax(xxx);
console.log(data2)
}
}
show()//输出对应逻辑的数据
//以上是async函数中 ajax返回正常的情况;当ajax返回出错时情况处理,直接在async函数中使用try{}catch(){}包含所有的await的ajax;
//loading层 的使用 直接在async函数中所有await之前开启loading层,之后关闭即可。
6. 前端性能优化的方法
https://www.cnblogs.com/xiaohuochai/p/9178390.html
7. 实现一个路由
1、监听 hashchange ,hash 改变的时候,根据当前的 hash 匹配相应的 html 内容,然后用 innerHTML 把 html 内容放进 router-view 里面。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta name="author" content="">
<title>原生模拟 Vue 路由切换</title>
<style type="text/css">
.router_box,
#router-view {
max-width: 1000px;
margin: 50px auto;
padding: 0 20px;
}
.router_box>a {
padding: 0 10px;
color: #42b983;
}
</style>
</head>
<body>
<div class="router_box">
<a href="/home" class="router">主页</a>
<a href="/news" class="router">新闻</a>
<a href="/team" class="router">团队</a>
<a href="/about" class="router">关于</a>
</div>
<div id="router-view"></div>
<script type="text/javascript">
function Vue(parameters) {
let vue = {};
vue.routes = parameters.routes || [];
vue.init = function() {
document.querySelectorAll(".router").forEach((item, index) => {
item.addEventListener("click", function(e) {
let event = e || window.event;
event.preventDefault();
window.location.hash = this.getAttribute("href");
}, false);
});
window.addEventListener("hashchange", () => {
vue.routerChange();
});
vue.routerChange();
};
vue.routerChange = () => {
let nowHash = window.location.hash;
let index = vue.routes.findIndex((item, index) => {
return nowHash == ('#' + item.path);
});
if (index >= 0) {
document.querySelector("#router-view").innerHTML = vue.routes[index].component;
} else {
let defaultIndex = vue.routes.findIndex((item, index) => {
return item.path == '*';
});
if (defaultIndex >= 0) {
window.location.hash = vue.routes[defaultIndex].redirect;
}
}
};
vue.init();
}
new Vue({
routes: [{
path: '/home',
component: "<h1>主页</h1><a href='https://github.com/biaochenxuying'>https://github.com/biaochenxuying</a>"
}, {
path: '/news',
component: "<h1>新闻</h1><a href='http://biaochenxuying.cn/main.html'>http://biaochenxuying.cn/main.html</a>"
}, {
path: '/team',
component: '<h1>团队</h1><h4>全栈修炼</h4>'
}, {
path: '/about',
component: '<h1>关于</h1><h4>关注公众号:BiaoChenXuYing</h4><p>分享 WEB 全栈开发等相关的技术文章,热点资源,全栈程序员的成长之路。</p>'
}, {
path: '*',
redirect: '/home'
}]
});
</script>
</body>
</html>
2、history路由主要是通过history.pushState()方法向浏览记录中添加一条历史记录,并同时触发js回调加载页面,history路由实现与hash路由的步骤类似,由于需要配置路由模式切换,页面中所有的a链接都采用了hash类型链接,history路由初始化时,需要拦截a标签的默认跳转
8. 数组最大差值
js方法一:
Array.prototype.outputMaxPrice = function outputMaxPrice (array) {
const item1 = Math.max.apply( Math, array );
const item2 = Math.min.apply( Math, array );
return item1 - item2;
}
const array = new Array;
array.outputMaxPrice ([1, 3, 63, 44]) // 62
js方法二:
var getMaxProfit = function(arr){
// 定义两个变量,分别存贮最大值和最小值
let maxNum = arr[0];
let minNum = arr[0];
for(let i = 0; i < arr.length; i++){
if(arr[i] > maxNum){
maxNum = arr[i];
}
if(arr[i] < minNum){
minNum = arr[i];
}
}
return maxNum - minNum;
}
getMaxProfit([1, 3, 63, 44]) // 62
9. CORS原理
相对JSONP,CORS支持POST提交,并且实施起来灰常简单,CORS原理只需要向响应头header中注入Access-Control-Allow-Origin,这样浏览器检测到header中的Access-Control-Allow-Origin,则就可以跨域操作了。
具体:https://www.cnblogs.com/keyi/p/6726089.html
10. select组件
编写一个选中框和一个下拉列表,点击选中框可以展示下拉,点击下拉选项,选中框展示点击的下拉选项,并将值赋值给点击事件,隐藏下拉列表
11. BFC的原理及应用场景
BFC,即Block Formatting Contexts(块级格式化上下文),它属于上述定位方案的普通流。
具有BFC特性的元素可以看做是隔离了的独立容器,容器里面的元素不会再布局上影响到外面的元素,并且BFC具有普通容器所没有的一些特性。
可以把BFC,理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。
BFC 布局规则
内部的Box会在垂直方向,一个接一个地放置。
Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
BFC的区域不会与float box重叠。
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
计算BFC的高度时,浮动元素也参与计算
触发BFC
只要元素满足下面任一条件即可触发BFC特性:
body根元素
浮动元素:float除none以外的值
绝对定位元素:position(absolute、fixed)
display为inline-block、table-cells、flex
overflow除了visible以外的值(hidden、auto、scroll)
12.从浏览器输入url直到页面渲染,期间有哪些步骤
1、DNS解析URL的过程
2、浏览器发送请求与服务器交互的过程
3、浏览器对接收到的html页面渲染的过程
一、DNS解析URL的过程
DNS解析的过程就是寻找哪个服务器上有请求的资源。因为ip地址不容易记忆,一般会使用URL域名(如www.baidu.com)作为网址。DNS解析就是将域名翻译成IP地址的过程。
具体过程:
1)浏览器缓存:浏览器会按照一定的频率 缓存DNS记录
2)操作系统缓存:如果浏览器缓存中找不到需要的DNS记录,就会取操作系统中找
3)路由缓存:路由器也有DNS缓存
4)ISP的DNS服务器:ISP有专门的DNS服务器应对DNS查询请求
5)根服务器:ISP的DNS服务器找不到之后,就要向根服务器发出请求,进行递归查询
二、浏览器与服务器交互过程
1)首先浏览器利用tcp协议通过三次握手与服务器建立连接
http请求包括header和body。header中包括请求的方式(get和post)、请求的协议 (http、https、ftp)、请求的地址ip、缓存cookie。body中有请求的内容。
2)浏览器根据解析到的IP地址和端口号发起http的get请求.
3)服务器接收到http请求之后,开始搜索html页面,并使用http返回响应报文
4)若状态码为200显示响应成功,浏览器接收到返回的html页面之后,开始进行页面的渲染
三、浏览器页面渲染过程
1)浏览器根据深度遍历的方式把html节点遍历成dom 树
2)将css解析成CSS DOM树
3)将dom树和CSS DOM树构造成render树
4)JS根据得到的render树 计算所有节点在屏幕中的位置,进行布局(回流)
5)遍历render树并调用硬件API绘制所有节点(重绘)
补充: 构造render渲染树的过程
从DOM树的根节点开始遍历每个可见的节点。
对于每个可见的节点,找到CSS树中的对应的规则,并且应用他们。
根据每个可见的节点及其对应的样式,组合生成渲染树。
13. 改变this的几种方式;apply/call/bind 有什么区别
对于 apply、call 二者而言,作用完全一样,只是接受参数的方式不太一样。
何时使用 apply、call,何时使用 bind 呢。简单的一个栗子:
var obj = {
x: 81,
};
var foo = {
getX: function() {
return this.x;
}
}
console.log(foo.getX.bind(obj)()); //81
console.log(foo.getX.call(obj)); //81
console.log(foo.getX.apply(obj)); //81
三个输出的都是81,但是注意看使用 bind() 方法的,他后面多了对括号。
也就是说,区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。
再总结一下:
apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
apply 、 call 、bind 三者都可以利用后续参数传参;
bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。
14. webpack配置项都有哪些,其中loader和plugin有什么区别
webpack配置项主要包括以下几个:
var config = {
entry: [
],
output: {
},
resolve: {
},
module: {
},
plugins: [
]
}
entry:入口,定义要打包的文件
output:出口,定义打包输出的文件;包括路径,文件名,还可能有运行时的访问路径(publicPath)参数
module: webpack将所有资源都看做是模块,而模块就需要加载器;
resolve:定义能够被打包的文件,文件后缀名
plugins:定义额外的插件
loader 和 plugin主要区别
loader 用于加载某些资源文件。 因为webpack 本身只能打包commonjs规范的js文件,对于其他资源例如 css,图片,或者其他的语法集,比如 jsx, coffee,是没有办法加载的。 这就需要对应的loader将资源转化,加载进来。从字面意思也能看出,loader是用于加载的,它作用于一个个文件上。
plugin 用于扩展webpack的功能。它直接作用于 webpack,扩展了它的功能。当然loader也时变相的扩展了 webpack ,但是它只专注于转化文件(transform)这一个领域。而plugin的功能更加的丰富,而不仅局限于资源的加载。
15. Array的方法
增删的方法:
push() 插入数组末尾,返回数组长度
unshift() 插入数组开头,返回数组长度
pop() 删除数组末尾,返回删除项
shift() 删除数组开头,返回删除项
重排序方法:
reverse() 将数组翻转
sort() 将数组按升序重排序
截取/合并:
concat() 合并,将添加的项合并到数组尾部 ,返回合并后的数组 (不改变原数组)
slice() 截取数组片段,eg:arr.slice(1,4),返回截取的数组(不改变原数组)
splice() 删除截取的片段,eg:arr.splice(1,4),返回截取后的数组
位置方法:
indexOf()
lastIndexOf()
迭代方法:
every() 对数组中的每一项都执行给定的函数,同时成立时,则返回true
filter() 对数组中的每一项都执行给定的函数,返回函数执行为true的项组成的数组
forEach() 对数组中的每一项执行给定的函数,但无返回值
map() 对数组中的每一项执行给定的函数,返回每次函数调用的结果组成的数组
some() 对数组中的每一项执行给定的函数,当执行项中有一个是true,则返回true
归并方法:
reduce()
reduceRight()
17. 异步有哪些场景,怎么解决异步
主流的解决方法主要有以下几种:
回调函数
事件触发
发布/订阅者模式
promise
generate
18.localStorage、sessionStorage 区别;应用业务场景
https://www.cnblogs.com/leftJS/p/10927013.html
19.如何区分行内、块级元素
块级元素 :总是以一个块的形式表现出来,并和同级的兄弟一次垂直排列,左右撑满,比如<li>,<p><hn>,总是不会排在同一行,而是和相邻的<li>垂直排列,简单来说,就是标准文档流下它会自动换行,并不会挤在一行上.就像柜台买票排队,按照正规流程,应该是自动排队,并不能挤在一条上在同一个窗口服务,那不是乱套了吗?但是特殊情况下还是有的(这个就是靠浮动来实现)
行内元素: 相邻元素之间横向排列,到最右端自动折行,比如<span>,<a>,也是运用他们的时候会自动挤到同一行上,除非空间不够了,才会去下一行.
20.ES6+新特性,经由babel编译后的代码,实现promise/promise.all/async/await
es6新特性:https://www.cnblogs.com/minghui007/p/8177925.html
1、 变量声明-let 与 const
let为JavaScript新增了块级作用域。
2、模版字符串
使用 反引号``(键盘上esc下面那个键) 将整个字符串包裹起来,而在其中使用 ${} 来包裹一个变量或者一个表达式
3、解构(destructuring)赋值
数组以序列号一一对应,这是一个有序的对应关系。
对象根据属性名一一对应,这是一个无序的对应关系。
4、展开运算符(spread operater)
在ES6中用...来表示展开运算符,它可以将数组方法或者对象进行展开。上栗子
5、arrow function箭头函数
6、函数参数的默认值
function add(x = 20) {
return x ;
}
7、对象字面量({})扩展
ES6针对对象字面量做了许多简化语法的处理
const person = {
name,
age
}
let obj = {
['h'+'ello']() {
return 'hi';
}
};
8、class、extend、super
class、extend、super这三个特性涉及了ES5中最令人头疼的的几个部分:构造函数、继承,原型...
ES6提供了更接近传统语言的写法,引入了Class(类)这个概念。新的class写法让对象原型的写法更加清晰、更像面向对象编程的语法,也更加通俗易懂。
9、模块的 Import 和 Export
import 用于引入模块,export 用于导出模块。
经由babel编译后的代码:https://blog.csdn.net/i10630226/article/details/78013968
21.vuex、redux流程有什么区别,哪种更好,如果你设计,能有什么改进
22.js的构造函数、工厂模式、单例模式、观察者模式、装饰器模式
23.选一到两个你比较满意或者印象深刻的项目,讲讲你在其中起到的作用,遇到过什么比较有挑战的问题,如何解决
24.vue、react、es6 等等 最近有什么新进展?
25.vue的观察者模式,有什么缺陷吗,尤雨溪vue3.0打算怎么优化,或者有什么其他改进点
26.变量提升、函数提升的code题
27.SSR服务端渲染了解过吗
28.vue和react对diff算法的优化有哪些;你觉得最新的这些框架和以前jquery相比有什么优势
29.bfs 和 dfs 算法