1.前端面试总结

1.知识点总结

HTML

浏览器盒子模型

一个盒子由外到内可以分成四个部分:margin(外边距)、border(边框)、padding(内边距)、content(内容)。会发现margin、border、padding是CSS属性,因此可以通过这三个属性来控制盒子的这三个部分。而content则是HTML元素的内容。

盒子的宽度 = 内容宽度 + 左填充 + 右填充 + 左边框 + 右边框 + 左边距 + 右边距

盒子的高度 = 内容高度 + 上填充 + 下填充 + 上边框 + 下边框 + 上边距 + 下边距

盒子的宽度 = width + padding-left + padding-right + border-left + border-right + margin-left + margin-right

盒子的高度 = height + padding-top + padding-bottom + border-top + border-bottom + margin-top + margin-bottom

box-sizing:content-box时,这种盒子模型成为标准盒子模型,当box-sizing: border-box时,这种盒子模型称为IE盒子模型。

1.HTML5新特性
(1)语义化标签

HTML5提供语义化标签,如:

<header><article><footer><nav><aside><section>等

(2)增强型表单

多个新的表单 Input 输入类型,如:

color,url,date等

这些新特性提供了更好的输入控制和验证。

(3)新增表单元素,如:

<output>,用于用于不同类型的输出,比如计算或脚本输出。

(4)新增表单属性,如:

placeholder 属性,简短的提示在用户输入值前会显示在输入域上。即我们常见的输入框默认提示,在用户输入后消失。

required  属性,是一个 boolean 属性。要求填写的输入域不能为空

min 和 max 属性,设置元素最小值与最大值。

step 属性,为输入域规定合法的数字间隔。

height 和 width 属性,用于 image 类型的 <input> 标签的图像高度和宽度。

autofocus 属性,是一个 boolean 属性。规定在页面加载时,域自动地获得焦点。

multiple 属性 ,是一个 boolean 属性。规定<input> 元素中可选择多个值。

3.新增视频 <video> 和音频 <audio> 标签

4.Canvas绘图

SVG 与 Canvas两者间的区别

  SVG 是一种使用 XML 描述 2D 图形的语言。

  Canvas 通过 JavaScript 来绘制 2D 图形。

  SVG 基于 XML,这意味着 SVG DOM 中的每个元素都是可用的。您可以为某个元素附加 JavaScript 事件处理器。

  在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形。

  Canvas 是逐像素进行渲染的。在 canvas 中,一旦图形被绘制完成,它就不会继续得到浏览器的关注。如果其位置发生变化,那么整个场景也需要重新绘制,包括任何或许已被图形覆盖的对象。

5.SVG绘图

6.地理定位 

window.navigator.geolocation {
    getCurrentPosition:  fn  用于获取当前的位置数据
    watchPosition: fn  监视用户位置的改变
    clearWatch: fn  清除定位监视
} 

7.拖放API

8.Web Worker

9.Web Storage

10.WebSocket

详情操作 见:https://www.w3school.com.cn/html5/html_5_video.asp

2.谈谈对websocket的理解

https://blog.csdn.net/github_37130188/article/details/89463183

HTTP和websocket区别

http协议是用在应用层的协议,他是基于tcp协议的,http协议建立链接也必须要有三次握手才能发送信息。
http链接分为短链接,长链接,短链接是每次请求都要三次握手才能发送自己的信息。即每一个request对应一个response。长链接是在一定的期限内保持链接。保持TCP连接不断开。客户端与服务器通信,必须要有客户端发起然后服务器返回结果。客户端是主动的,服务器是被动的。

WebSocket
WebSocket他是为了解决客户端发起多个http请求到服务器资源浏览器必须要经过长时间的轮训问题而生的,他实现了多路复用,他是全双工通信。在webSocket协议下客服端和浏览器可以同时发送信息。

建立了WebSocket之后服务器不必在浏览器发送request请求之后才能发送信息到浏览器。这时的服务器已有主动权想什么时候发就可以发送信息到服务器。而且信息当中不必在带有head的部分信息了与http的长链接通信来说,这种方式,不仅能降低服务器的压力。而且信息当中也减少了部分多余的信息。

3.浏览器模型常见的对象

window history location xhr对象

4.Cookie、Session(LocalStorage、SessionStorage)的理解与区别:

cookie 由浏览器保存的以下几块信息构成:名称、值、域、路径、失效时间、安全标志 

cookie 的优缺点

  • 优点:

    • 可控制过期时间,使其不会长期有效
    • 可扩展、可用性比较好,可跨域共享
    • 可加密减少cookie被破解的可能性
    • 兼容性好
  • 缺点:

    • 数量和长度有限制
    • 在请求头上带着数据安全性差

localStorage 与 sessionStorage 的区别总结

  • H5的两种存储技术的最大区别就是生命周期
    • localStorage是本地存储,存储期限不限;
    • sessionStorage是会话存储,页面关闭数据就会丢失。
  • sessionStorage 有单标签页限制,localStorage 则没有。

Web Storage 和 Cookie 的区别总结

  • Web Storage 是为了更大容量存储设计的,而Cookie的大小是受限的。

  • cookie 在每次请求一个新的页面的时候都会被发送过去,在浏览器和服务器间来回传递,这样无形中浪费了带宽。

  • cookie 可以设定访问域,在同源窗口中可以共享,而 web storage 受同源策略限制。

  • 但是Cookie也是不可以或缺的:Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在 ,而Web Storage仅仅是为了在本地“存储”数据而生。

5、页面DOM渲染过程、重流:

6.文件上传的实现:

 7.用j原生Js实现数组去重

function merge(arr) {

if (!Array.isArray(arr) || arr.length == 0)

return [];

var ret = [] ;

for (var i = 0; i < arr.length; i++) {

// 或者 ret.indexOf(arr[i] == -1)

 if (arr.indexOf(arr[i]) == i)

{ret.push(arr[i]);}

}  

 return ret;

 } 

8.实现函数的柯里化

const curry = ( fn, arr = []) => {
    return (...args) => { 

        return ( a => {   //a是一个数组
            if(a.length === fn.length) {
                return fn(...a)
            }else{
                return curry(fn, a)
            }
        })([...arr, ...args])  //这里把arr和args摊开成一个数组赋值给a

    }
}

或者:const curry = ( fn, arr = []) => (...args) => ( a => a.length === fn.length? fn(...a) : curry(fn, a))([...arr, ...args])
let curryPlus = curry((a,b,c,d)=>a+b+c+d)

curryPlus(1,2,3)(4) //返回10
curryPlus(1,2)(4)(3) //返回10
curryPlus(1,2)(3,4) //返回10

二:CSS

CSS优雅地实现垂直水平居中

1.块级元素水平居中:对其自身设置 margin:0 auto

2.行内元素水平居中对其父元素设置 text-align: center

3.单行行内元素垂直居中:

  • 设置 line-height 与 height 一样高。(推荐)
  • 设置padding-top padding-bottom

4.多行行内元素垂直居中:

使用flex布局(推荐)

5.块级元素垂直水平居中的解决方案

<body>
    <div id="block">
        //这里面是一些内容,可能是文字、图片等
    </div>
</body>

 基于绝对定位的解决方案

1.1 利用绝对定位 + margin 反向偏移

早期的垂直居中方法,要求元素具有固定宽和高。

#block {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 18em;
    height: 6em;
    margin-top: -3em;
    margin-left: -9em;
    background: yellow;  
}

 优化:借助强大的calc()函数(定宽高)

#block {
    position: absolute;
    top: calc(50% - 3em);
    left: calc(50% - 9em);
    width: 18em;
    height: 6em;
    background: yellow;
}
可以参考 https://www.jianshu.com/p/7cde2a816dd9

 
 清除浮动:
1.clear:both
2.overflow: auto
3.伪元素来清除浮动
 

BFC (Block formatting context) “块级格式化上下文”

 
10:Promise的用法以及实现原理
promise是一种异步编程的解决方案。用于解决回调地狱的问题。

首先,Promise是一个对象,如同其字面意思一样,代表了未来某时间才会知道结果的时间,不受外界因素的印象。Promise一旦触发,其状态只能变为fulfilled或者rejected,并且已经改变不可逆转。Promise的构造函数接受一个函数作为参数,该参数函数的两个参数分别为resolve和reject,其作用分别是将Promise的状态由pending转化为fulfilled或者rejected,并且将成功或者失败的返回值传递出去。then有两个函数作为Promise状态改变时的回调函数,当Promise状态改变时接受传递来的参数并调用相应的函数。then中的回调的过程为异步操作。catch方法是对.then(null,rejectFn)的封装(语法糖),用于指定发生错误时的回掉函数。一般来说,建议不要再then中定义rejected状态的回调函数,应该使用catch方法代替。all和race都是竞速函数,all结束的时间取决于最慢的那个,其作为参数的Promise函数一旦有一个状态为rejected,则总的Promise的状态就为rejected;而race结束的时间取决于最快的那个,一旦最快的那个Promise状态发生改变,那个其总的Promise的状态就变成相应的状态,其余的参数Promise还是会继续进行的。

  当然在es7时代,也出现了await/async的异步方案,这会是我们以后谈论的。

参考出处:

https://www.cnblogs.com/lunlunshiwo/p/8852984.html


11:
css中单位px和em,rem的区别

px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。(引自CSS2.0手册)

 em是相对长度单位。相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸

  任意浏览器的默认字体高都是16px。所有未经调整的浏览器都符合: 1em=16px。那么12px=0.75em,10px=0.625em。为了简化font-size的换算,需要在css中的body选择器中声明Font-size=62.5%,这就使em值变为 16px*62.5%=10px, 这样12px=1.2em, 10px=1em, 也就是说只需要将你的原来的px数值除以10,然后换上em作为单位就行了。


EM特点 

1. em的值并不是固定的;

2. em会继承父级元素的字体大小。

px 是一个绝对单位,em 和 rem 是一个相对单位,em 参考的是当前元素的字符大小,rem 参考的是页面根元素 html 的字体大小


 1em=16px  1 px=0.75 rem

所以我们在写CSS的时候,需要注意两点:

1. body选择器中声明Font-size=62.5%;

2. 将你的原来的px数值除以10,然后换上em作为单位;

3. 重新计算那些被放大的字体的em数值。避免字体大小的重复声明。

 

 1.js原型链:

每个构造函数都有原型对象;每个对象都会有构造函数;每个构造函数的原型都是一个对象;那么这个原型对象也会有构造函数;那么这个原型对象的构造函数也会有原型对象;这样就会形成一个链式的结构,称为原型链。

hasOwnProperty 方法是 Javascript 中唯一一个处理对象属性而不会往上遍历原型链的。

https://juejin.im/post/5c4fdbae6fb9a049b07dc084

2.深浅拷贝:

浅拷贝:浅拷贝就是拷贝了一层,除了对象是拷贝的引用类型,其他都是直接将值传递,有自己的内存空间的;

深拷贝:但是深拷贝就会拷贝多层,即使是嵌套了对象,也会都拷贝出来。

对象只有一层的话可以使用上面的:Object.assign()函数是深拷贝 ,否则是浅拷贝
target:目标对象。
sources:任意多个源对象。
返回值:目标对象会被返回

1.深拷贝的实现方式:
(1)手动复制:把一个对象的属性复制给另一个对象的属性

var obj1 = { a: 10, b: 20, c: 30 };
var obj2 = { a: obj1.a, b: obj1.b, c: obj1.c };
obj2.b = 100;
console.log(obj1);
// { a: 10, b: 20, c: 30 } <-- 沒被改到
console.log(obj2);

(2)用JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象。

var obj1 = { body: { a: 10 } };
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.body.a = 20;
console.log(obj1);
// { body: { a: 10 } } <-- 沒被改到
console.log(obj2);
// { body: { a: 20 } }
console.log(obj1 === obj2);
// false
console.log(obj1.body === obj2.body);

但是这种方法也有不少坏处,譬如它会抛弃对象的constructor。也就是深拷贝之后,不管这个对象原来的构造函数是什么,在深拷贝之后都会变成Object。

也就是说,只有可以转成JSON格式的对象才可以这样用,像function没办法转成JSON。


(3)对象只有一层的话可以使用上面的:Object.assign()函数是深拷贝 ,否则是浅拷贝

(4)递归拷贝

(5)使用Object.create()方法

直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果


 

 

 

详情:https://blog.csdn.net/weixin_37719279/article/details/81240658?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

react中key值的作用:

key 帮助 React 识别哪些元素改变了,比如被添加或删除。因此你应当给数组中的每一个元素赋予一个确定的标识

3.闭包:

当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包。闭包的作用,改变变量的作用域。
例1:
const foo = () =>{
const a =0;
return fun = () =>{
   a+=1;
  } 
let f1=foo()
f1();
例2:

function outer() {

var a = 100; // outer的局部变量

function inner() { // 闭包
console.log(a);
}

return inner; // 没有这条语句,闭包起不到在outer外部访问变量a的作用~
}
console.log(a); // 在外部直接访问a出错

var test = outer(); // outer运行完返回inner,赋值给test
test(); // 100,执行test(),相当于执行inner(),这样就可以访问到outer内部的a了

 

4.ES6常用功能与常见问题分析

1.js常用的数据类型:

基础类型:字符串、布尔型、数字、null、undefined、symbol(es6新增)、BigInt(和number相比不会失去精度)

复杂类型:Object、array、function

 

 5.react生命周期?

初始化阶段:
getDefaultProps:获取实例的默认属性
getInitialState:获取每个实例的初始化状态
componentWillMount:组件即将被装载、渲染到页面上(在整个生命周期中只会触发一次)
render:组件在这里生成虚拟的 DOM 节点
componentDidMount:组件真正在被装载之后(在整个生命周期中只会触发一次)
运行中状态:
componentWillReceiveProps:组件将要接收到属性的时候调用
shouldComponentUpdate:组件接受到新属性或者新状态的时候(可以返回 false,接收数据后不更新,阻止 render 调用,后面的函数不会被继续执行了)
componentWillUpdate:组件即将更新不能修改属性和状态
render:组件重新描绘
componentDidUpdate:组件已经更新

销毁阶段:
componentWillUnmount:组件即将销毁

新增:

简单的理解就说从props中获取state,这个生命周期的功能实际上就是将传入的props映射到state上面

  getDerivedStateFromProps是一个静态函数,也就是这个函数不能通过this访问到class的属性,也并不推荐直接访问属性。而是应该通过参数提供的nextProps以及prevState来进行判断,根据新传入的props来映射到state

  如果props传入的内容不需要影响到你的state,那么就需要返回一个null

 


 getSnapshotBeforeUpdate() {}
  在最近的更改被提交到DOM元素前,使得组件可以在更改之前获得当前值,此生命周期返回的任意值都会传给componentDidUpdate()。

  用于替换 componentWillUpdate,该函数会在update后 DOM 更新前被调用,用于读取最新的 DOM 数据,返回值将作为 componentDidUpdate 的第三个参数

  在最新的渲染数据提交给DOM前会立即调用,它让你在组件的数据可能要改变之前获取他们

链接:https://www.jianshu.com/p/b331d0e4b398#31-getderivedstatefrompropsnextprops-prevstate

6.this.setStatue 是异步还是同步?

  1. setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。
  2. setState的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,当然可以通过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果。
  3. setState 的批量更新优化也是建立在“异步”(合成事件、钩子函数)之上的,在原生事件和setTimeout 中不会批量更新,在“异步”中如果对同一个值进行多次 setState , setState 的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新。

参考:

为什么虚拟 dom 会提高性能

虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。

用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中当状态变更的时候,重新构造一棵新的对象树。

然后用新的树和旧的树进行比较,记录两棵树差异把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。

diff算法:

把树形结构按照层级分解,只比较同级元素。

给列表结构的每个单元添加唯一的 key 属性,方便比较。

React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)。

合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每一个事件循环结束, React 检查所有标记 dirty 的 component 重新绘制.

选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能。

react 工作原理:

React 会创建一个虚拟 DOM(virtual DOM)。当一个组件中的状态改变时,React 首先会通过 "diffing" 算法来标记虚拟 DOM 中的改变;
第二步是调节(reconciliation),会用 diff 的结果来更新 DOM。

refs是什么: 

Refs是能访问DOM元素或组件实例的一个函数;

react 中得key?
如果你没有指定任何 key,React 会发出警告,并且会把数组的索引当作默认的 key。但是如果想要对列表进行重新排序、新增、删除操作时,把数组索引作为 key 是有问题的。显式地使用 key={i} 来指定 key 确实会消除警告,但是仍然和数组索引存在同样的问题,所以大多数情况下最好不要这么做。

7.redux

redux 是一个应用数据流框架,主要是解决了组件间状态共享的问题,原理是集中式管理,主要有三个核心方法,action,store,reducer,
工作流程是 view 调用 store 的 dispatch 接收 action 传入 store,reducer 进行 state 操作,view 通过 store 提供的 getState 获取最新的数据。
新增 state,对状态的管理更加明确,通过 redux,流程更加规范了,减少手动编码量,提高了编码效率,
同时缺点时当数据更新时有时候组件不需要,但是也要重新绘制,有些影响效率。
一般情况下,我们在构建多交互,多数据流的复杂项目应用时才会使用它们。

参考:https://www.cnblogs.com/strong-FE/p/10901011.html

8.箭头函数的this指向问题

箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象), 定义它的时候,可能环境是window

9.css优先级

CSS优先级顺序

!important > 行内样式>ID选择器 > 类选择器 > 标签 > 通配符 > 继承 > 浏览器默认样式

10.js垃圾回收机制

  Js具有自动垃圾回收机制。垃圾收集器会按照固定的时间间隔周期性的执行。

标记清除:工作原理:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。

引用计数 :工作原理:跟踪记录每个值被引用的次数。

什么情况会引起内存泄漏?

1.    意外的全局变量引起的内存泄漏。

原因:全局变量,不会被回收。

解决:使用严格模式避免。

2.    闭包引起的内存泄漏

原因:闭包可以维持函数内局部变量,使其得不到释放。

解决:将事件处理函数定义在外部,解除闭包,或者在定义事件处理函数的外部函数中,删除对dom的引用。

3.    没有清理的DOM元素引用

原因:虽然别的地方删除了,但是对象中还存在对dom的引用

解决:手动删除。

4.    被遗忘的定时器或者回调

原因:定时器中有dom的引用,即使dom删除了,但是定时器还在,所以内存中还是有这个dom。

解决:手动删除定时器和dom。

5.    子元素存在引用引起的内存泄漏

原因:div中的ul li  得到这个div,会间接引用某个得到的li,那么此时因为div间接引用li,即使li被清空,也还是在内存中,并且只要li不被删除,他的父元素都不会被删除。

解决:手动删除清空。

11.es6新特性

1.let 和 const 命令

另外两种声明变量的方法:import命令和class

let 和 const 相同的地方

1).只在声明所在的块级作用域内有效
2).不可重复声明
3).同样存在暂时性死区,只能在声明的位置后面使用。

2.变量的解构赋值

 

3.箭头函数

规则一:箭头函数只能用赋值式写法,不能用声明式写法

规则二:如果参数只有一个,可以不加括号,如果没有参数或者参数多于一个就需要加括号

规则三:如果函数体只有一句话,可以不加花括号

规则四:如果函数体没有括号,可以不写return,箭头函数会帮你return

箭头函数的this指向问题: 箭头函数this的定义:箭头函数中的this是在定义函数的时候绑定,而不是在执行函数的时候绑定

4.Set数据结构

5.Map数据结构

6. 模版字符串 

 7.for...of和for...in

8. class

 9.浅复制

const obj = Object.assign({}, objA, objB)
10.数组:forEach()
1map()
2 filter()
3 reduce()
4 some()
5 every()

11.

11import 和 export

12  Promise(承诺)

13  Promise是一个构造函数,自己身上有all、reject、resolve这几个眼熟的方法,原型上有then、catch等同样很眼熟的方法。

12.js宏观任务和微观任务

宏任务:可以理解是每次执行栈执行的代码就是一个宏任务

微任务),可以理解是在当前 task 执行结束后立即执行的任务

1.宏任务:

分类:setTimeout setInterval requrestAnimationFrame

1>宏任务所处的队列就是宏任务队列

2>第一个宏任务列中只有一个任务,执行主线程的js代码

3>宏任务队列可以有多个

2.微任务:

分类:new promise().then(回调) process.nextTick

1.微任务所处的队列 就是微任务队列

2.只有一个微任务队列

3.在上一个宏任务队列执行完毕后如果有微任务队列就会执行微任务队列中所有的任务

总结下运行机制:
  • 执行一个宏任务(栈中没有就从事件队列中获取)
  • 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
  • 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
  • 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
  • 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)



链接:https://www.jianshu.com/p/667a20d008cf

13.js事件循环机制

  • 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数
  • 当指定的事情完成时,Event Table会将这个函数移入Event Queue
  • 当栈中的代码执行完毕,执行栈(call stack)中的任务为空时,就会读取任务队列(Event quene)中的事件,去执行对应的回调
  • 如此循环,形成js的事件循环机制(Event Loop

链接:https://www.jianshu.com/p/667a20d008cf

14.js事件流的三个阶段

事件的处理过程主要有三个阶段:捕获阶段,目标阶段,冒泡阶段;

1.捕获阶段:当我们在 DOM 树的某个节点发生了一些操作(例如单击、鼠标移动上去),就会有一个事件发射过去。这个事件从 Window 发出,不断经过下级节点直到触发的目标节点。在到达目标节点之前的过程,就是捕获阶段(Capture Phase)。事件由页面元素接收,逐级向下,到具体的元素。

2.目标阶段:当事件不断的传递直到目标节点的时候,最终在目标节点上触发这个事件,就是目标阶段。具体的元素本身

3.冒泡阶段:事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为不具体的节点。跟捕获相反,具体元素本身,逐级向上,到页面元素(我们平时用的事件绑定就是利用的事件冒泡的原理)。

事件捕获:当使用事件捕获时,父级元素先触发,子元素后触发。

事件冒泡:当使用事件冒泡时,子级元素先触发,父元素后触发。

 W3C : 任何事件发生时,先从顶层开始进行事件捕获,直到事件触发到达事件源,再从事件源向上进行事件捕获(事件冒泡)。

事件传播的阻止方法:

在W3C中,使用stopPropagation()方法。

在IE下使用cancelBubble = true方法。

阻止默认行为:

在W3c中,使用preventDefault()方法。



原文链接:https://blog.csdn.net/SummerJX/article/details/81626960

15.onload 什么时候加载?    在html全部加载完了才执行

16.json和jsonp区别:

 

17.三次握手:

 

19 . 跨域请求:

什么是同源策略?
同源策略/SOP(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。

1、 通过jsonp跨域

$.ajax({
    url: 'http://www.domain2.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 请求方式为jsonp
    jsonpCallback: "handleCallback",    // 自定义回调函数名
    data: {}
});


<script>
    var script = document.createElement('script');
    script.type = 'text/javascript';

    // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
    script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
    document.head.appendChild(script);

    // 回调执行函数
    function handleCallback(res) {
        alert(JSON.stringify(res));
    }
 </script>


handleCallback({"status": true, "user": "admin"})

jsonp缺点:只能实现get一种请求。


2、 document.domain + iframe跨域

accept-origin增加白名单跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 window.postMessage跨域 拿到iframe里面得数据。


6、 跨域资源共享(CORS)

普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。

需注意的是:由于同源策略的限制,所读取的cookie为跨域请求接口所在域的cookie,而非当前页。如果想实现当前页cookie的写入,

目前,所有浏览器都支持该功能(IE8+:IE8/9需要使用XDomainRequest对象来支持CORS)),CORS也已经成为主流的跨域解决方案。


7、 nginx代理跨域

1、 nginx配置解决iconfont跨域

浏览器跨域访问js、css、img等常规静态资源被同源策略许可,但iconfont字体文件(eot|otf|ttf|woff|svg)例外,此时可在nginx的静态资源服务器中加入以下配置。

location / {
  add_header Access-Control-Allow-Origin *;
}
2、 nginx反向代理接口跨域

跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。

实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。

nginx具体配置:

#proxy服务器
server {
    listen       81;
    server_name  www.domain1.com;

    location / {
        proxy_pass   http://www.domain2.com:8080;  #反向代理
        proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
        index  index.html index.htm;

        # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
        add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时,可为*
        add_header Access-Control-Allow-Credentials true;
    }
}

1.) 前端代码示例:

var xhr = new XMLHttpRequest();

// 前端开关:浏览器是否读写cookie
xhr.withCredentials = true;

// 访问nginx中的代理服务器
xhr.open('get', 'http://www.domain1.com:81/?user=admin', true);
xhr.send();

2.) Nodejs后台示例:

 
var http = require('http');
var server = http.createServer();
var qs = require('querystring');

server.on('request', function(req, res) {
    var params = qs.parse(req.url.substring(2));

    // 向前台写cookie
    res.writeHead(200, {
        'Set-Cookie': 'l=a123456;Path=/;Domain=www.domain2.com;HttpOnly'   // HttpOnly:脚本无法读取
    });

    res.write(JSON.stringify(params));
    res.end();
});

server.listen('8080');
console.log('Server is running at port 8080...');


8、 nodejs中间件代理跨域
9、 WebSocket协议跨域

https://segmentfault.com/a/1190000011145364

18.判断是否是一个数组:

1.instanceof 

instanceof运算符用于检验构造函数的prototype属性是否出现在对象的原型链中的任何位置,返回一个布尔值。
 
let a = [];
a instanceof Array; //true
let b = {};
b instanceof Array; //false
 

在上方代码中,instanceof运算符检测Array.prototype属性是否存在于变量a的原型链上,显然a是一个数组,拥有Array.prototype属性,所以为true。

需要注意的是,prototype属性是可以修改的,所以并不是最初判断为true就一定永远为真。

其次,当我们的脚本拥有多个全局环境,例如html中拥有多个iframe对象,instanceof的验证结果可能不会符合预期,例如:

 

//为body创建并添加一个iframe对象
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
//取得iframe对象的构造数组方法
xArray = window.frames[0].Array;
//通过构造函数获取一个实例
var arr = new xArray(1,2,3);
arr instanceof Array;//false

 
2.Object.prototype.toString().call()可以获取到对象的不同类型
let a = [1,2,3]
Object.prototype.toString.call(a) === '[object Array]';//true


3.Array.isArray()方法

function checkIsArray(o){

return Object.prototype.toString.call(o) == "[object Array]" &&"push" in o;

}

通过constructor判断

let a = [1,3,4];
a.constructor === Array;//true
同样,这种判断也会存在多个全局环境的问题,导致的问题与instanceof相同。

//为body创建并添加一个iframe标签
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
//取得iframe对象的构造数组方法
xArray = window.frames[window.frames.length-1].Array;
//通过构造函数获取一个实例
var arr = new xArray(1,2,3);
arr.constructor === Array;//false

高阶组件(HOC)m

HOC就是一个函数,且该函数接受一个组件作为参数,并返回一个新组件。

1.mvc和mvvm区别?

MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式:

  • Model(模型)表示应用程序核心(如数据库)。

  • View(视图)显示效果(HTML页面)。

  • Controller(控制器)处理输入(业务逻辑)。

MVC 模式同时提供了对 HTML、CSS 和 JavaScript 的完全控制。

MVC模式:

  M:Model(数据模型),用于存放数据
  V:View(视图),也就是用户界面
  C:Controller是Model和View的协调者,Controller把Model中的数据拿过来给View使用。Controller可以直接与Model和View进行通信,而View不能与Controller直接通信。,当有数据更新时,Model也要与Controller进行通信,这个时候就要用Notification和KVO,这个方式就像发广播一样,Model发信号,Controller设置接收监听信号,当有数据更新是就发信号给Controller,Model和View不能直接通信,这样违背MVC设计原则。View与Controller通信需要利用代理协议的方式,Controller可以直接根据Model决定View的展示。View如果接受响应事件则通过delegate,target-action,block等方式告诉Controller的状态变化。Controller进行业务的处理,然后再控制View的展示。



  MVC:
    Controller负责将Model的数据用View显示出来
    用户操作> View (负责接受用户的输入操作)>Controller(业务逻辑处理)>Model(数据持久化)>View(将结果通过View反馈给用户)

  缺点:1.所有业务逻辑都在Controller里操作,逻辑复杂且不利于维护,
     2.大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。
        3.当 Model 频繁发生变化,需要主动更新到View ;当用户的操作导致Model发生变化,同样需要将变化的数据同步到Model中, 这样的工作不仅繁琐,而且很难维护复杂多变的数据状态。


由于MVC模式的缺陷,MVC的变种模式衍生出MVVM模式

MVVM模式:
  核心是提供对View 和 ViewModel 的双向数据绑定,View和Model之间并没有直接的联系,而是通过ViewModel进行交互,View的变动,自动反映在ViewModel上,反之亦然,这样就保证视图和数据的一致性。

  M:Movel(数据模型)
  V:View
  VM:ViewModel 是一个同步View 和 Model的对象。View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互。ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
    VM双向绑定:在 MVVM 框架中,View(视图) 和 Model(数据) 是不可以直接通讯的,在它们之间存在着 ViewModel 这个中间介充当着观察者的角色。当用户操作 View(视图),ViewModel 感知到变化,然后通知 Model 发生相应改变;反之当 Model(数据) 发生改变,ViewModel 也能感知到变化,使 View 作出相应更新。这个一来一回的过程就是我们所熟知的双向绑定。




2.react框架的原理?

react的设计原理就是其引入的虚拟dom机制:
1、react用javascript在浏览器端实现了一套虚拟dom api。
2、基于react开发的时候所有的dom构造都是基于虚拟dom进行的
3、每当有state更改的时候,react就重新render一整套虚拟dom树,
react机制会将当前的整个dom树和上一次的dom树进行对比
取到diff,进行真实的dom更改。
4、其实state也有一部分实现的是数据、html片段绑定,
直接更新的数据是包含的


React对Virtual DOM树进行层级控制,只会对相同层级的DOM节点进行比
较,即同一个父元素下的所有子节点,当发现节点已经不存在了,则会删除掉
该节点下所有的子节点,不会再进行比较。这样只需要对DOM树进行一次遍
历,就可以完成整个树的比较。
即使说a节点以及他的子节点被移动,但是react只关注同级比较,在第二层
把a及其子节点删了,在第三层再重新创建,所以diff运算量大,影响性能
不建议setState直接更改树的结构。最好是state颗粒度小,只改变树中
的某一个小的节点,那么diff的时候只会深度比较这一个小节点。


3.js设计模式?
https://segmentfault.com/a/1190000018800165

redux 就是订阅模式啊,然后组件自动发现props 或者 state 变化自动更新,这种叫观察者模式
然后呢一个redux 只有一个store 这种叫单列模式,工厂模式之类的,就是抽出一个公共方法

4.移动端如何实现适配?
(1)通过媒体查询的方式即CSS3的meida queries
(2)以天猫首页为代表的 flex 弹性布局
(3)以淘宝首页为代表的 rem+viewport缩放
(4)rem 方式

5.react中遇到的问题 ,怎么解决的?
6.http请求的全部过程

https://blog.csdn.net/ailunlee/article/details/90600174

7.React优点
React主要用于构建UI。你可以在React里传递多种类型的参数,如声明代码,帮助你渲染出UI、也可以是静态的HTML DOM元素、也可以传递动态变量、甚至是可交互的应用组件。

 

   React特性如下: 

    1.声明式设计:React采用声明范式,可以轻松描述应用。

    2.高效:React通过对DOM的模拟,最大限度地减少与DOM的交互。

    3.灵活:React可以与已知的库或框架很好地配合。

  优点: 1. 速度快:在UI渲染过程中,React通过在虚拟DOM中的微操作来实现对实际DOM的局部更新。

      2. 跨浏览器兼容:虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的API,甚至在IE8中都是没问题的。

      3. 模块化:为你程序编写独立的模块化UI组件,这样当某个或某些组件出现问题是,可以方便地进行隔离。

      4. 单向数据流:Flux是一个用于在JavaScript应用中创建单向数据层的架构,它随着React视图库的开发而被Facebook概念化。

      5. 同构、纯粹的javascript:因为搜索引擎的爬虫程序依赖的是服务端响应而不是JavaScript的执行,预渲染你的应用有助于搜索引擎优化。

      6. 兼容性好:比如使用RequireJS来加载和打包,而Browserify和Webpack适用于构建大型应用。它们使得那些艰难的任务不再让人望而生畏。

  缺点: 1. React本身只是一个V而已,并不是一个完整的框架,所以如果是大型项目想要一套完整的框架的话,基本都需要加上ReactRouter和Flux才能写大型应用。




 webpack 面试题

1.websocket的断线重连机制?
2.dva和redux相比较优缺点?
3.购物车如何实现?
1。是否需要设备同步,如果需要就记录到后端,如果不需要可以记录在前端的localstorage,但是大部分都记录在后端,或者在未登陆的状态下,加购物车的情况,可以先记录到前端,登陆后进行合并传给后端。
4.前端性能优化?

1.加载优化


加载过程是最为耗时的过程,可能会占到总耗时的80%的时间,是优化的重点。


1.减少HTTP请求


2.合并图片,使用雪碧图


3.缓存,减少向服务器的请求数,节省加载时间,所有的静态资源都要在服务器端设置缓存,并且尽量使用长Cache(长Cache资源的更新可使用时间戳)


  a) 缓存一切可缓存的资源 


  b)使用长Cache(使用时间戳更新cache)


  c)使用外联式引用css、js


3.压缩html、css、javascript


4.无阻塞 


  写在HTML头部的JavaScript(无异步),和写在HTML标签中的Style会阻塞页面的渲染,因此CSS放在页面头部并使用Link方式引入,避免在HTML标签中写Style,JavaScript放在页面尾,部或使用异步方式加载


5.使用首屏加载


首屏加快显示,可以大大提升用户对页面速度的感知,因此应尽量针对首屏的快速显示做优化


6.按需加载


  a) LazyLoad
  b) 滚屏加载
  c) 通过Media Query加载


7.预加载


大型重资源页面(如游戏)可使用增加Loading的方法,资源加载完成后再显示页面。但Loading时间过长,会造成用户流失
对用户行为分析,可以在当前页加载下一页资源,提升速度
  a) 可感知Loading(如进入空间游戏的Loading)
  b) 不可感知的Loading(如提前加载下一页)


8.压缩图片


9.减少cookie


9.避免重定向


10.异步加载第3方资源


11.CDN预热


可以将静态资源提前预热处理,加速用户的访问速度。


5.虚拟dom的缺点?
6.webpack 打包流程

https://www.cnblogs.com/gaoht/p/11310365.html

原文地址:https://www.cnblogs.com/web-zxq/p/12445632.html