前端面试总结

废话少说,本文分四个部分,css、js、知识点一、知识点二、React(部分问题没有给出答案,后续更新)

css面试问题


一、垂直居中问题

https://www.cnblogs.com/clj2017/p/9293363.html

1、设置行高

2、弹性布局(父元素设置display:flex;子元素设置align-slef:center)

3、伪元素

父元素设置:before

content:“”;

display:inline-block;

vertical-align:middle;

height:100%;

4:父元素设置display:table

子元素设置display:table-cell;

vertical-align:middle;

二、弹性布局

http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

容器属性、项目属性

1、容器属性

flex-direction:row | row-reverse | column  | column-reverse

决定项目的排列顺序

flex-wrap:wrap | nowrap | wrap-reverse

是否换行

flex-flow:<flex-direction> | <flex-wrap>

flex-direction和flex-wrap简写形式

justify-content:flex-start | flex-end | center | space-between | space-around

项目在主轴上的对齐方式

align-items:flex-start | flex-end | center | baseline | stretch

项目在交叉轴的对齐方式

align-content:flex-start | flex-end | center | stretch | space-between | space-around

定义了多跟轴线的对齐方式 ,如果项目只有一根轴线,该属性不起作用。

2、项目属性

order

定义项目的排列顺序,值越小排列越靠前,默认为0.

flex-grow

定义项目的放大比例,默认为0,即如果存在剩余空间也不放大

如果所有项目的flex-grow都为1,等分剩余空间。如果一个项目的flex-grow为2,其他项目的flex-grow都为1,前者占用的剩余空间将比其他项多一倍。

flex-shrink

定义项目的缩小比例,默认为1,即如果空间不足,该项目将缩小

flex-basis

分配多余空间之前项目占据的主轴空间

flex

flex-grow | flex-shrink | flex-basis的简写。

align-self:auto | flex-start | flex-end | center | baseline | stretch

单个项目在交叉的对齐方式,可与其他项目不一样

三、BFC

https://blog.csdn.net/sinat_36422236/article/details/88763187

1、定义:块级格式化上下文

2、触发BFC的条件

⑴浮动

⑵position:absolute fixed

⑶display:inline-block | table-cell | flex |

⑷overflow:hidden | scroll | auto

3、BFC解决的问题

(1)避免margin重叠

(2)解决浮动重叠

(3)解决高度塌陷问题

四、清除浮动的方式

清除浮动主要是为了解决父级元素因为子级浮动引起的内部高度为0的问题。

1、额外标签

在父元素下写一个标签:用clear:both

2、overflow:hidden;触发bfc

3、伪元素:after{clear:both;content:"";display:block;}


js

一、解决浮点数计算问题

const floatAdd = (arg1, arg2) => {

  var r1, r2, m;

  r1 = arg1.toString().split(".")[1].length;

  r2 = arg2.toString().split(".")[1].length;

  m = Math.pow(10, Math.max(r1, r2));

  var rs = (arg1 * m + arg2 * m) / m;

  console.log(rs);

  return rs;

};

二、数组扁平化

1、递归

2、转化为字符串

var rs = [1, 2, 3, [4, 5, [8, 78], 6]]

  .toString()

  .split(",")

  .map(item => {

    return Number(item);

  });

console.log(rs);

三、两个数组求交集

function intersection(arr1,arr2){

return arr1.filter(item=>{

if(arr2.indexOf(item)>-1){

return item

}

})

}

四、数组去重

var arr2 = [2, 1, 3, 1];

var arr3 = [];

arr2.map(item => {

  if (arr3.indexOf(item) == -1) {

    arr3.push(item);

  }

});

console.log(arr3);

五、深拷贝和浅拷贝

浅拷贝方法

1、展开运算符 ...

2、Object.assign({},对象)

深拷贝方法

1、JSON.parse(JSON.stringify(对象))

该方法有局限性

会忽略undefined

会忽略symbol

不能序列化函数

不能解决循环引用的对象

2、递归

function deepClone(obj) {

  //判断是否为引用类型

  function isobj(o) {

    return (typeof o == "object" || typeof o == "function") && o !== null;

  }

  if (!isobj(obj)) {

    throw new Error("非对象");

  }

  //判断是否为数组,是的话解构数组否则结构对象

  let isArray = Array.isArray(obj);

  let newobj = isArray ? [...obj] : { ...obj };

  Object.keys(newobj).forEach(item => {

    newobj[item] = isobj(newobj[item]) ? deepClone(newobj[item]) : newobj[item];

  });

  return newobj;

}

六、继承

1、原型继承(通过prototype)

function Parent(name, age) {

  this.name = "小头爸爸";

  this.age = 40;

}

function Child() {}

Child.prototype = new Parent();

var child = new Child();

console.log(child.name);

2、构造函数继承()

function Parent(name) {

  this.name = name;

  this.age = 40;

}

function Child(name) {

  Parent.call(this, name);

}

var child = new Child("大头儿子");

console.log(child.name);

console.log(child.age);

3、组合继承

function Box(age) {

this.name = ['Lee', 'Jack', 'Hello']

this.age = age;

}

Box.prototype.run = function () {

return this.name + this.age;

};

function Desk(age) {

Box.call(this, age); //对象冒充

}

Desk.prototype = new Box(); //原型链继承

var desk = new Desk(100);

alert(desk.run());

4、class继承

class Parent {

  constructor(value) {

    this.value = value;

  }

  getvalue() {

    console.log(this.value);

  }

}

class Child extends Parent {

  constructor(value) {

    super(value);

    this.value = value;

  }

}

let child = new Child(1);

child.getvalue();

组合继承优点是可以用构造函数传参,可以复用父类的函数,不会与父类引用属性共享,

缺点是子类原型上多了不需要的父类属性

七、手写call、apply、bind

//手写call、apply、bind

// Function.prototype.mycall = function(context) {

//   if (typeof this !== "function") {

//     throw new TypeError("Error");

//   }

//   context = context || window;

//   context.fn = this;

//   let args = [...arguments].slice(1);

//   let result = context.fn(...args);

//   delete context.fn;

//   return result;

// };

// function demo(num1, num2) {

//   let rs = num1 + num2;

//   console.log(rs);

//   return rs;

// }

// demo.mycall(this, 1, 2);

//手写apply

// Function.prototype.myapply = function(context) {

//   if (typeof this !== "function") {

//     throw new Error("Error");

//   }

//   context = context || window;

//   context.fn = this;

//   let result;

//   if (arguments[1]) {

//     result = context.fn(...arguments[1]);

//   } else {

//     result = context.fn();

//   }

//   delete context.fn;

//   return result;

// };

// function demo(num1, num2) {

//   let rs = num1 + num2;

//   console.log(rs);

//   return rs;

// }

// demo.myapply(this, [1, 2]);

//手写bind

Function.prototype.mybind = function(context) {

  if (typeof this !== "function") {

    throw new Error("Error");

  }

  console.log(arguments instanceof Object);

  let args = [...arguments].slice(1);

  let self = this;

  return function F() {

    if (this instanceof F) {

      return new self(...args, ...arguments);

    } else {

      return self.apply(context, args.concat(...arguments));

    }

  };

};

function demo(num1, num2) {

  let rs = num1 + num2;

  console.log(rs);

  return rs;

}

demo.mybind(this, 1)(3, 6);

八、一个按钮挂载两个onclick事件

1、写两个.addEventListener(click,fn1 )

addEventListener(click,fn2)

2、写onclick=“fn1();n2()”


知识点1


一、http缓存

二、git常用命令

三、axios  拦截器作用 底层原理

axios是什么

axios是基于promise机制实现的异步链式请求框架,体积小。

底层原理:promise+ajax

基本api

axios.get()get请求 获取数据

axios.post()post请求 提交数据

axios.put()put请求 更新数据

axios.delete() 删除数据

用法

对象使用:axios.get('url',params).then(response=>{

console.log(response)

})

函数使用:axios({

url:"url",

method:"method",

headers: {'X-Requested-With': 'XMLHttpRequest'},

}).then((res)=>{console.log(err)}).catch((err)=>{console.log(err)})

axios.defaults.baseURL = 'https://api.example.com';(设置基础路径)

axios.interceptors.request.use()请求拦截器

axios.interceptors.response.use()响应拦截器

用法:

axios.interceptors.request.use((config)=>{

return config

},(error)=>{

return promise.reject(error)

})//两种拦截器用法一样。

token怎么从后端获取

四、优化

1、图片优化

⑴很多装饰类的用css去完成。

⑵雪碧图

⑶小图使用base64格式

⑷选择正确的格式

能使用webp就使用webp(webp兼容性不好,很多浏览器不支持)

小图使用PNG,大部分图标可以用SVG代替

照片使用JPEG

2、DNS预解析

DNS解析也是需要时间的,可以通过预解析的方式来预先获得域名

<link rel="dns-prefetch" href="//域名">

3、节流

如果滚动事件会发起网络请求,我们不希望用户在滚动中一直发送网络请求,而是而一段时间发送一次,对于这种情况我们可以使用节流

实现的主要思路:就是将当前时间和上一次执行时间作对比,如果差值大于设置的等待时间就执行函数。

4、防抖

点击按钮会触发网络请求,我们不希望每次点击都会触发网络请求,而是用户点击按钮一段时间后没有再次点击的情况才去发起网络请求,对于这种情况我们可以使用防抖。

// func是用户传入需要防抖的函数// wait是等待时间const debounce = (func, wait = 50) => {

  // 缓存一个定时器id  let timer = 0  // 这里返回的函数是每次用户实际调用的防抖函数  // 如果已经设定过定时器了就清空上一次的定时器  // 开始一个新的定时器,延迟执行用户传入的方法  return function(...args) {

    if (timer) clearTimeout(timer)

    timer = setTimeout(() => {

      func.apply(this, args)

    }, wait)

  }

}

5、预加载

有些资源不需要马上用到,但是需要尽早获取,这时候可以用到预加载

预加载其实是声明式的fetch,强制浏览器请求资源,并且不会阻塞onload事件,可以使用以下代码实现预加载

<link rel="preload" href="资源">

优点:降低首屏加载时间,缺点是兼容性不好

6、预渲染

可以通过预渲染将下载的文件在后台渲染

实现:<link rel="prerender" href="资源">

预渲染虽然可以提高页面的加载速度,但是要确保该页面大概率会被用户在之后打开,否则就是白白浪费资源去渲染。

7、懒执行

将某些逻辑使用时在计算。该技术可以用于首屏优化,一般可以通过定时器或者事件调用来唤醒

8、懒加载

将不关键的资源延后加载

原理是只加载可视区域

五、当浏览器输入url之后

https://www.cnblogs.com/confach/p/10050013.html

DNS查询

TCP连接

发送HTTP请求

Server处理HTTP请求并返回HTTP报文

浏览器解析并render页面

HTTP连接断开

六、forEach和map的区别

1、返回值不一样,forEach返回值是undefined,map返回值是一个新的数组

2、forEach不可中断,除非抛出异常。

七、this指向问题

1、定时器的this指向问题

setTimeout(function(){

console.log(this.name)

},1000)

一般情况下如果在定时器内部使用普通函数,this指向window

改变this指向的方法

⑴that绑定this

⑵使用bind,bind方法返回一个新函数,call和apply立即执行函数,所以只能使用bind方法,否则就失去了定时器的作用

⑶使用箭头函数,箭头函数没有this指向,它的this是继承外部的作用域。

2、如果直接调用函数,函数不管放在哪个地方,this指向都是window

3、如果对象调用函数,this指向被调用的对象

4、对于new的方式,this永远绑定在实例化对象上,不可改变。

5、箭头函数没有this指向,它的this是继承外部的作用域。

八、webpack相关内容

webpack相关内容https://www.runoob.com/w3cnote/es6-setup.html

webpack功能:

1将sass/less 等预编译的css语言转换成浏览器识别的css文件

2能够将多个预编译文件打包成一个文件

3 打包image/styles/assets/scrips/等前端常用的文件

4 搭建开发环境开启服务器

5 监视文件改动,热部署。

webpack构建过程

从entry里配置的module开始递归解析entry依赖的所有module

每找到一个module,就会根据配置的loader去找对应的转换规则

对module进行转换后,再解析出当前module依赖的module

这些模块会以entry为单位分组,一个entry和其所有依赖的module被分到一个组Chunk

最后webpack会把所有Chunk转换成文件输出

在整个流程中webpack会在恰当的时机执行plugin里定义的逻辑

webpack打包原理

将所有依赖打包成一个bundle.js,通过代码分割成单元片段按需加载

什么是entry,output?

entry 入口,告诉webpack要使用哪个模块作为构建项目的起点,默认为./src/index.js

output 出口,告诉webpack在哪里输出它打包好的代码以及如何命名,默认为./dist

什么是loader,plugins?

loader是用来告诉webpack如何转换某一类型的文件,并且引入到打包出的文件中。

plugins(插件)作用更大,可以打包优化,资源管理和注入环境变量

什么是bundle,chunk,module?

bundle是webpack打包出来的文件,chunk是webpack在进行模块的依赖分析的时候,代码分割出来的代码块。module是开发中的单个模块

如何利用webpack来优化前端性能

1. 压缩代码。uglifyJsPlugin 压缩js代码, mini-css-extract-plugin 压缩css代码

2. 利用CDN加速,将引用的静态资源修改为CDN上对应的路径,可以利用webpack对于output参数和loader的publicpath参数来修改资源路径

3. 删除死代码(tree shaking),css需要使用Purify-CSS

4. 提取公共代码。webpack4移除了CommonsChunkPlugin (提取公共代码),用optimization.splitChunks和optimization.runtimeChunk来代替

补充CDN

CDN(Content Delivery Network)是指内容分发网络,也称为内容传送网络,在现有互联网基础上建立一个内容分发平台专门为网站提供服务,是为加快网络访问速度而被优化的网络覆盖层,

原理

CDN的基本原理是广泛采用各种缓存服务器,将这些缓存服务器分布到用户访问相对集中的地区或网络中,在用户访问网站时,利用全局负载技术将用户的访问指向距离最近的工作正常的缓存服务器上,由缓存服务器直接响应用户请求


知识点2


一、websocket介绍:https://www.liaoxuefeng.com/wiki/1022910821149312/1103303693824096

websocket简单介绍

https://www.jianshu.com/p/970dcfd174dc

二、koa

Koa 是一个新的 web 框架,由 Express 幕后的原班人马打造, 致力于成为 web 应用和 API 开发领域中的一个更小、更富有表现力、更健壮的基石。 通过利用 async 函数,Koa 帮你丢弃回调函数,并有力地增强错误处理。 Koa 并没有捆绑任何中间件, 而是提供了一套优雅的方法,帮助您快速而愉快地编写服务端应用程序。

三、express

基于nodejs的web开发框架

四、nginx

Nginx (engine x) 是一个高性能的HTTP反向代理web服务器,特点是占有内存少,并发能力强,事实上nginx的并发能力在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东新浪网易腾讯淘宝等。

功能:

Nginx是一个HTTP服务器,可以将服务器上的静态文件(如HTML、图片)通过HTTP协议展现给客户端

可以实现负载均衡、虚拟主机

什么是负载均衡

当网站访问量非常大,网站站长开心赚钱的同时,也摊上事儿了。因为网站越来越慢,一台服务器已经不够用了。于是将同一个应用部署在多台服务器上,将大量用户的请求分配给多台机器处理。同时带来的好处是,其中一台服务器万一挂了,只要还有其他服务器正常运行,就不会影响用户使用。

Nginx可以通过反向代理来实现负载均衡。

虚拟主机

有的网站访问量大,需要负载均衡。然而并不是所有网站都如此出色,有的网站,由于访问量太小,需要节省成本,将多个网站部署在同一台服务器上。

例如将www.aaa.com和www.bbb.com两个网站部署在同一台服务器上,两个域名解析到同一个IP地址,但是用户通过两个域名却可以打开两个完全不同的网站,互相不影响,就像访问两个服务器一样,所以叫两个虚拟主机。

五、nodejs

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。 Node.js 使用了一个事件驱动、非阻塞式 I/O 的模型。 [1] 

Node 是一个让 JavaScript 运行在服务端的开发平台,它让 JavaScript 成为与PHPPythonPerlRuby 等服务端语言平起平坐的脚本语言

特点:

单线程

Node可以在不新增额外线程的情况下,依然可以对任务进行并发处理 —— Node.js是单线程的。它通过事件循环(event loop)来实现并发操作,对此,我们应该要充分利用这一点 —— 尽可能的避免阻塞操作,取而代之,多使用非阻塞操作。

非阻塞IO

V8虚拟机

事件驱动

六、事件驱动

所谓事件驱动,简单地说就是你点什么按钮(即产生什么事件),电脑执行什么操作(即调用什么函数).当然事件不仅限于用户的操作. 事件驱动的核心自然是事件。从事件角度说,事件驱动程序的基本结构是由一个事件收集器、一个事件发送器和一个事件处理器组成。事件收集器专门负责收集所有事件,包括来自用户的(如鼠标、键盘事件等)、来自硬件的(如时钟事件等)和来自软件的(如操作系统、应用程序本身等)。事件发送器负责将收集器收集到的事件分发到目标对象中。事件处理器做具体的事件响应工作,它往往要到实现阶段才完全确定,因而需要运用虚函数机制(函数名往往取为类似于HandleMsg的一个名字)。对于框架的使用者来说,他们唯一能够看到的是事件处理器。这也是他们所关心的内容

七、非阻塞i/o

非阻塞I/O是指以异步来执行函数,先执行同步任务,耗时任务放在事件队列中,以此轮询执行。

八、webpack和gulp

二者比较

gulp它是基于流的自动化构建工具。有task处理机制,入口是src,通过管道pipe打包文件。配置文件是gulpfile.js

webpack的两大特点:1模块化 2打包。Webpack实现了模块化开发和文件处理。它能够将各个模块进行按需加载,不会导致加载了无用或冗余的代码。配置文件webpack.config.js

功能:

1将sass/less 等预编译的css语言转换成浏览器识别的css文件

2能够将多个预编译文件打包成一个文件

3 打包image/styles/assets/scrips/等前端常用的文件

4 搭建开发环境开启服务器

5 监视文件改动,热部署。

九、模块化

模块化的优点

解决命名冲突

提供复用性

提高代码可维护性

实现:

CommonJs

随着Javasript应用进军服务器端,业界急需一种标准的模块化解决方案,于是,CommonJS(www.commonjs.org)应运而生。它最初是由Kevin Dangoor在他的这篇博文中首次提出。

这是一种被广泛使用的Javascript模块化规范,大家最熟悉的Node.js应用中就是采用这个规范。在Node.js中,内置了module对象用来定义模块, require函数用来加载模块文件,代码如下:

// utils.js 模块定义var add = function(a, b) {

    return a + b;

};

module.exports = {

    add: add

};// 加载模块var utils = require('./utils');console.log(utils.add(1, 2));

此种模块化方案特点就是:同步阻塞式加载,无法实现按需异步加载。另外,如果想要在浏览器中使用CommonJS模块就需要使用Browserify进行解析:

npm install browserify -g

browserify utils.js > bundle.js

当然,你也可以使用gulp, webpack等工具进行解析打包后引入到浏览器页面中去。

ES6 Modules

对于ES6来说,不必再使用闭包和封装函数等方式进行模块化支持了。在ES6中,从语法层面就提供了模块化的功能。然而受限于浏览器的实现程度,如果想要在浏览器中运行,还是需要通过Babel等转译工具进行编译。ES6提供了import和export命令,分别对应模块的导入和导出功能。具体实例如下:

// demo-export.js 模块定义var name = "scq000"var sayHello = (name) => {

  console.log("Hi," + name);

}export {name, sayHello};// demo-import.js 使用模块import {sayHello} from "./demo-export";

sayHello("scq000");

对于具体的语法细节,想必大家在日常使用过程中都已经轻车熟路了。但对于ES6模块化来说,有以下几点特性是需要记住的:

ES6使用的是基于文件的模块。所以必须一个文件一个模块,不能将多个模块合并到单个文件中去。

ES6模块API是静态的,一旦导入模块后,无法再在程序运行过程中增添方法。

ES6模块采用引用绑定(可以理解为指针)。这点和CommonJS中的值绑定不同,如果你的模块在运行过程中修改了导出的变量值,就会反映到使用模块的代码中去。所以,不推荐在模块中修改导出值,导出的变量应该是静态的。

ES6模块采用的是单例模式,每次对同一个模块的导入其实都指向同一个实例

Webpack中的模块化方案

作为现代化的前端构建工具,Webpack还提供了丰富的功能能够使我们更加轻易地实现模块化。利用Webpack,你不仅可以将Javascript文件进行模块化,同时还能针对图片,css等静态资源进行模块化。你可以在代码里使用CommonJS, ES6等模块化语法,打包的时候你也可以根据需求选择打包类型,如UMD, AMD等:

module.exports = {

  //...

  output: {

    library: 'librayName',

    libraryTarget: 'umd', // 配置输出格式

    filename: 'bundle.js'

  }

};

另外,ES6模块好处很多,但是并不支持按需加载的功能, 而按需加载又是Web性能优化中重要的一个环节。好在我们可以借助Webpack来弥补这一缺陷。Webpack v1版本提供了require.ensureAPI, 而2.x之后使用了import()函数来实现异步加载。具体的代码示例可以查看我之前所写的前端性能优化之加载技术 这篇文章。

十、mvvm mvc

PS:MVVM(Model-View-ViewModel), 源自于经典的 Model–View–Controller(MVC)模式。MVVM 的出现促进了 GUI 前端开发与后端业务逻辑的分离,极大地提高了前端开发效率。MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用。View 层展现的不是 Model 层的数据,而是 ViewModel 的数据,由 ViewModel 负责与 Model 层交互,这就完全解耦了 View 层和 Model 层,这个解耦是至关重要的,它是前后端分离方案实施的最重要一环。

十一、ajax 、axios、fetch

Ajax

传统 Ajax 指的是 XMLHttpRequest(XHR), 最早出现的发送后端请求技术,隶属于原始js中,核心使用XMLHttpRequest对象,多个请求之间如果有先后关系的话,就会出现回调地狱。

JQuery ajax 是对原生XHR的封装,除此以外还增添了对JSONP的支持。经过多年的更新维护,真的已经是非常的方便了,;如果是硬要举出几个缺点,那可能只有:

1.本身是针对MVC的编程,不符合现在前端MVVM的浪潮

2.基于原生的XHR开发,XHR本身的架构不清晰。

3.JQuery整个项目太大,单纯使用ajax却要引入整个JQuery非常的不合理(采取个性化打包的方案又不能享受CDN服务)

4.不符合关注分离(Separation of Concerns)的原则

5.配置和调用方式非常混乱,而且基于事件的异步模型不友好。

PS:MVVM(Model-View-ViewModel), 源自于经典的 Model–View–Controller(MVC)模式。MVVM 的出现促进了 GUI 前端开发与后端业务逻辑的分离,极大地提高了前端开发效率。MVVM 的核心是 ViewModel 层,它就像是一个中转站(value converter),负责转换 Model 中的数据对象来让数据变得更容易管理和使用,该层向上与视图层进行双向数据绑定,向下与 Model 层通过接口请求进行数据交互,起呈上启下作用。View 层展现的不是 Model 层的数据,而是 ViewModel 的数据,由 ViewModel 负责与 Model 层交互,这就完全解耦了 View 层和 Model 层,这个解耦是至关重要的,它是前后端分离方案实施的最重要一环。

axios

axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,只不过它是Promise的实现版本,符合最新的ES规范,它本身具有以下特征:

注:

1、从浏览器创建XMLHttpRequest

2、node.js发送http请求

3、支持promiseAPI

4、拦截请求和响应

5、转换请求和响应

6、取消请求

7、JSON数据的自动转换

8、客户端对防止XSRF的支持

PS:防止CSRF:就是让你的每个请求都带一个从cookie中拿到的key, 根据浏览器同源策略,假冒的网站是拿不到你cookie中得key的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略。

axios既提供了并发的封装,而且体积也较小,当之无愧现在最应该选用的请求的方式。

fetch

fetch号称是AJAX的替代品,是在ES6出现的,使用了ES6中的promise对象。Fetch是基于promise设计的。Fetch的代码结构比起ajax简单多了,参数有点像jQuery ajax。但是,一定记住fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。

fetch的优点:

1.符合关注分离,没有将输入、输出和用事件来跟踪的状态混杂在一个对象里

2.更好更方便的写法

坦白说,上面的理由对我来说完全没有什么说服力,因为不管是Jquery还是Axios都已经帮我们把xhr封装的足够好,使用起来也足够方便,为什么我们还要花费大力气去学习fetch?

我认为fetch的优势主要优势就是:

1.  语法简洁,更加语义化

2.  基于标准 Promise 实现,支持 async/await

3.  同构方便,使用 [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch)

4.更加底层,提供的API丰富(request, response)

5.脱离了XHR,是ES规范里新的实现方式

十二、有关于异步的问题

promise

是异步编程的一种解决方案。

从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。

Promise 状态以及状态的特点

Promise 异步操作有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。除了异步操作的结果,任何其他操作都无法改变这个状态。

Promise 对象只有:从 pending 变为 fulfilled 和从 pending 变为 rejected 的状态改变。只要处于 fulfilled 和 rejected ,状态就不会再变了即 resolved(已定型)。

状态的缺点

无法取消 Promise ,一旦新建它就会立即执行,无法中途取消。

如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。

当处于 pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。、

then 方法接收两个函数作为参数,第一个参数是 Promise 执行成功时的回调,第二个参数是 Promise 执行失败时的回调,两个函数只会有一个被调用。

generator

yield是ES6的新关键字,使生成器函数执行暂停,yield关键字后面的表达式的值返回给生成器的调用者。它可以被认为是一个基于生成器的版本的return关键字。

yield关键字实际返回一个IteratorResult(迭代器)对象,它有两个属性,value和done,分别代表返回值和是否完成。

yield无法单独工作,需要配合generator(生成器)的其他函数,如next,懒汉式操作,展现强大的主动控制特性。

function *gen() {

    yield 'hello';

    yield 'world';

    return true;

}

以上代码定义了一个简单的 generator,看起来就像一个普通的函数,区别是function关键字后面有个*号,函数体内可以使用yield语句进行流程控制。

 var iter = gen();

 var a = iter.next();

 console.log(a); // {value:'hello', done:false}

 var b = iter.next();

 console.log(b); // {value:'world', done:false}

 var c = iter.next();

 console.log(c); // {value:true, done:true}

当执行gen()的时候,并不执行 generator 函数体,而是返回一个迭代器。迭代器具有next()方法,每次调用 next() 方法,函数就执行到yield语句的地方。next() 方法返回一个对象,其中value属性表示 yield 关键词后面表达式的值,done 属性表示是否遍历结束。generator 生成器通过next和yield的配合实现流程控制,上面的代码执行了三次 next() ,generator 函数体才执行完毕。

async

async 函数返回一个 Promise 对象

function testAwait(){  return new Promise((resolve) => {      setTimeout(function(){          console.log("testAwait");

          resolve();

      }, 1000);

  });} async function helloAsync(){  await testAwait();

  console.log("helloAsync");

}helloAsync();// testAwait// helloAsync

await针对所跟不同表达式的处理方式:

Promise 对象:await 会暂停执行,等待 Promise 对象 resolve,然后恢复 async 函数的执行并返回解析值。

非 Promise 对象:直接返回对应的值。

十三、Object.keys()和Reflect.ownKeys()区别

Object.keys()返回属性key,但不包括不可枚举的属性

Reflect.ownKeys()返回所有属性key

他们两个都不能遍历原型上的属性

扩展

for in

for in一般用于遍历对象的属性;

作用于数组的for in除了会遍历数组元素外,还会遍历自定义可枚举的属性,以及原型链上可枚举的属性;

作用于数组的for in的遍历结果是数组的索引,且都为字符串型,不能用于运算;

某些情况下,可能按照随机顺序遍历数组元素;

for of

ES6中添加的循环语法;

for of支持遍历数组、类对象(例如DOM NodeList对象)、字符串、Map对象、Set对象;

for of不支持遍历普通对象,可通过与Object.keys()搭配使用遍历;

for of遍历后的输出结果为数组元素的值;

十四、页面卡顿的原因

1、js运行时间太长

2、head加载js时一直没加载出来

3、dom过多

4、首屏加载资源过大(解决:默认资源站位)

十五、浏览器存储(cookie 、webstorage)

https://www.cnblogs.com/qiujianmei/p/10824682.html


React

一、子组件向父组件传值

父子组件通信不仅可以传值,还可以传递方法,父组件将更新数据的方法拿给子组件使用,子组件将自身的数据传入这个方法并调用,以此来改变父组件的数据。

就是父组件给子组件传递一个方法,子组件将自己的数据传入这个方法并调用,就能改变父组件数据

二、父组件调用子组件的方法

先向子组件传方法,子组件通过父组件传递的方法向父组件传递方法,父组件获取到子组件的方法直接调用。

三、state和prop的区别

2-1.prop用于定义外部接口,state用于记录内部状态

2-2,prop 的赋值在外部世界使用组件时,state的赋值在组件内部,

2-3,组件不应该改变prop的值,而state存在的目的就是让组件来改变的

四、修改数据应该在哪个生命周期里面

didMount、didUpdate()

五、虚拟dom

1、浏览器资源对dom节点开销很大,而且频繁改变dom结点,会引发重绘和回流,非常影响性能。

2、虚拟dom存在的意义就是为了减少对实际dom的操作,js运行速度很快,通过对比新旧dom,有针对性的把差异部分渲染到页面上

3、虚拟dom原理:

⑴用js模拟dom树,并渲染dom树

⑵比较新老dom树,得到比较的差异对象

⑶把差异对象应用到渲染的dom树

4、js创建虚拟dom

5、diff算法

作用:是用来计算出 Virtual DOM 中被改变的部分,然后针对该部分进行原生DOM操作。

createElement(tag,props,children)

策略:策略一(tree diff):

Web UI中DOM节点跨层级的移动操作特别少,可以忽略不计。

  策略二(component diff):

拥有相同类的两个组件 生成相似的树形结构,

拥有不同类的两个组件 生成不同的树形结构。

  策略三(element diff):

对于同一层级的一组子节点,通过唯一id区分。

六、react生命周期

https://www.cnblogs.com/kdcg/p/9182393.html

1、construtor():构造函数

组建加载前最先调用一次,仅调用一次

作用:定义状态机变量

2、componentWillMount

组件初始渲染(render()被调用)前调用,仅调用一次。

如果这个函数调用的setState改变了组件的某些状态,react会等待setState完成后再渲染组件

注意子组件也有componentWillMount函数,在父组件的该函数调用后在调用。

3、render()

执行:componentWillMount调用之后,componentDidMount调用之前

作用:渲染挂载组件。

触发:⑴初始化加载页面,⑵状态机改变setState,⑶接受新的props(父组件更新)

注意:这是组件必要参数,不能在该函数内使用setState改变状态机

4、componentDidMount()

执行:render()之后被调用,仅调用一次。

作用:渲染挂载组件

注意:子组件也有该函数,在父组件调用前调用,如果该函数有setState改变状态机,将重新渲染组件,如果需要在页面初始化之后才改变状态机的,可以将网络请求放在该函数内。

5、componentWillReceiveProps()

执行:组件渲染后,当组件接收新的参数时被调用,

6、shouldComponentUpDate(nextProps,nextState)

执行:组件执行render()函数之后,接收新的props或state时被调用,即每次执行setState都会执行该函数,来判断是否重新渲染组件,默认返回true,接收两个参数。

作用:如果有些变化不需要执行渲染组件,可在该函数内阻止,

注意:不能在该函数内使用setState来改变状态机。

7、componentDidUpdate()

执行:组件重新渲染后调用,初始化渲染的时候该方法不会被调用。

作用:使用该方法可以在组件更新后操作dom元素

8、componentWillUnmount()

执行:组件卸载之前被调用

作用:在该方法中执行必要的清理,比如无效的定时器

注意:当一个页面中存在父子组件的时候,要特别注意componentDidMount的使用,因为子组件componentDidMount会比父组件先调用,从而引起父子组件传参错误

七、Component与PureComponent的区别

https://www.cnblogs.com/ly0612/p/11954414.html

PureComponent简单实现了shouldComponentUpdate()的功能。当然数据结构比较复杂就不行了。

PureComponent缺点

可能会因深层的数据不一致而产生错误的否定判断,从而shouldComponentUpdate结果返回false,界面得不到更新。

八、怎么写一个组件

https://blog.csdn.net/donspeng/article/details/83421136

组件目的是为了提高代码复用性,另外,组件必须功能单一,复用性高。如果想实现复用性强的特点的话,可以用高阶组件的思想,传参数通过props

九、connect()参数有几个

函数将被调用两次。第一次是设置参数,第二次是组件与 Redux store 连接:connect(mapStateToProps, mapDispatchToProps, mergeProps)(MyComponent)。

十、路由

十一、react优化

十二、服务器渲染

十三、react hooks方法有哪些方法

1、基础 Hook

useState

useEffect

useContext

2、额外的 Hook

useReducer

useCallback

useMemo

useRef

useImperativeHandle

useLayoutEffect

useDebugValue

十四、setState

什么时候setState是同步的

1、React通过addEventListener直接添加事件处理函数,

2、通过setTimeout/setInterval产生异步调用

原理解析:

在React的setState函数实现中,会根据一个变量 isBatchingUpdate 来判断是直接同步更新this.state还是放到队列中异步更新 。这个变量默认为false即同步执行,而当 React 在调用事件处理函数之前就会调用这个 batchedUpdates,这个函数会把isBatchingUpdate变为true,然后异步执行setState。

React使用了事务的机制,React的每个生命周期和合成事件都处在一个大的事务当中。在事务的前置钩子中调用batchedUpdates方法修改isBatchingUpdates变量为true,在后置钩子中将变量置为false。原生绑定事件和setTimeout异步的函数没有进入到React的事务当中,或者当他们执行时,刚刚的事务已近结束了,后置钩子触发了,所以此时的setState会直接进入非批量更新模式,表现在我们看来成为了同步SetState

十五、浅谈redux

最外层是Provider(react-redux解构出来)<Provider store={store}>

然后是store, store里面是reducer

reducer传两个参数(state,action)返回新的state

页面用connect(mapstate,dispatchstate,组件)或者使用装饰器

为什么reducer是纯函数

因为不能改变输入值state,说白了就是reducer传state和action返回新的state

为什么这样设计

因为页面渲染需要比较新旧state,react比较state比较的是地址(也就是浅比较,如果深比较耗费性能)所以必须返回新的state,否则页面不更新

首先得先知道什么是纯函数

1、相同的输入永远返回相同的输出

2、不能修改输入值

3、不依赖外部环境

4、无任何副作用

十六、React组件有那些

可分为函数组件,class组件、渲染组件、组合组件、有状态组件、无状态组件、高阶组件、自定义组件

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容

  • JS中的块级作用域 1.with 2.try.. catch 3.let, const 变量提升和函数提升 包括变...
    杰米桀弥阅读 729评论 1 3
  • 前端目录 HTML相关 CSS相关 JAVASCRIPT相关 DOM相关 HTTP相关 VUE相关 算法相关 网络...
    keyuan0214阅读 452评论 0 2
  • 在找工作的这段时间,其实面试了挺多的公司,关于前端技术方面被提问到了很多,常见的几类问题,我会在下文中一一给你解释...
    Marin_chen阅读 587评论 0 8
  • 面试题链接地址 https://juejin.im/post/5cbff661e51d456e693f48ec#h...
    祝家庄打烊阅读 525评论 0 1
  • 1.不包含掘金小册 掘金小册的内容就不在这总结了,下边的内容是其他一些小细节,面试分为笔试和口头面对面交流。本大纲...
    足够幸运阅读 489评论 0 2