@[TOC] 前端面试题
基础篇
1 HTML5、CSS3 里面都新增了那些新特性?
-
HTML5
新的语义标签
article 独立的内容。
aside 侧边栏。
header 头部。
nav 导航。
section 文档中的节。
footer 页脚。
画布(Canvas) API
地理(Geolocation) API
本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
sessionStorage 的数据在浏览器关闭后自动删除
新的技术webworker, websocket, Geolocation
拖拽释放(Drag and drop) API
音频、视频API(audio,video)
表单控件,calendar、date、time、email、url、searc -
CSS3
2d,3d变换
Transition, animation
媒体查询
新的单位(rem, vw,vh 等)
圆角(border-radius),阴影(box-shadow),对文字加特效(text-shadow),线性渐变(gradient),旋转(transform)transform:rotate(9deg) scale(0.85,0.90) translate(0px,-30px) skew(-9deg,0deg);//旋转,缩放,定位,倾斜
rgba
2、画一个三角形?
.a {
width: 0;
height: 0;
border-width: 100px;
border-style: solid;
border-color: transparent #0099CC transparent transparent;
transform: rotate(90deg); /*顺时针旋转90°*/
}
<div class="a"></div>
3、实现水平垂直居中
<div class="md-warp">
<span class="md-main"></span>
</div>
.md-warp{
width: 400px;
height: 300px;
max-width: 100%;
border: 1px solid #000;
}
.md-main{
display: block;
width: 100px;
height: 100px;
background: #f00;
}
//1-------+元素负做边距margin-left为宽度的一半
.md-wrap{
position:relative;
}
.md-main{
position:absolute;
left:50%;
margin-left:-50px
}
//2-----有些时候元素宽度不是固定的,依然可以使用定位法实现水平居中用到css3中的transform属性中的translate
.md-warp{
position: relative;
}
// 注意此时md-main不设置width为100px
.md-main{
position: absolute;
left: 50%;
-webkit-transform: translate(-50%,0);
-ms-transform: translate(-50%,0);
-o-transform: translate(-50%,0);
transform: translate(-50%,0);
}
4、什么是Promise?我们用Promise来解决什么问题?回调地狱 ,代码难以维护
在传统的异步编程中,如果异步之间存在依赖关系,我们就需要通过层层嵌套回调来满足这种依赖,如果嵌套层数过多,可读性和可维护性都变得很差,产生所谓“回调地狱”,而Promise将回调嵌套改为链式调用,增加可读性和可维护性。
Promise是一个构造函数,自己身上有all、reject、resolve这几个眼熟的方法,原型上有then、catch等同样很眼熟的方法。
promise可以支持多个并发的请求,获取并发请求中的数据
这个promise可以解决异步的问题,本身不能说promise是异步的
all的用法:谁跑的慢,以谁为准执行回调。all接收一个数组参数,里面的值最终都算返回Promise对象
race的用法:谁跑的快,以谁为准执行回调
5、async / await
async用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。
async 函数返回的是一个 Promise 对象, Promise 的特点——无等待,所以在没有 await 的情况下执行 async 函数,它会立即执行,返回一个 Promise 对象,并且,绝不会阻塞后面的语句。这和普通返回 Promise 对象的函数并无二致
async/await 的优势在于处理 then 链
Promise 通过 then 链来解决多层回调的问题,现在又用 async/await 来进一步优化它
async 经过 babel 处理后的代码看过吗
为什么js单线程
6、如何解决跨域
- 通过jsonp跨域
- document.domain + iframe跨域
- location.hash + iframe
- window.name + iframe跨域
- postMessage跨域
- 跨域资源共享(CORS)
- nginx代理跨域
- nodejs中间件代理跨域
- WebSocket协议跨域
7、jsonp实现以及优缺点
不管是我们的script标签的src还是img标签的src,或者说link标签的href他们没有被同源策略所限制,比如我们有可能使用一个网络上的图片,就可以请求得到;所以利用同源策略漏洞,将访问地址放在下面的标签的路径中,
- 优点:
兼容性比较好,可用于解决主流浏览器的跨域数据访问的问题
不受到同源策略的限制,在请求完毕后可以通过调用 callback 的方式回传结果 - 缺点:
仅支持get请求;
具有局限性,不安全,可能会受到XSS攻击;
只支持跨域 HTTP 请求这种情况,不能解决不同域的两个页面之间如何进行 Javascript 调用的问题
8、sessionStorage、localStorage和cookie的区别
- 存储大小限制,cookie数据不能超过4K,如会话标识。sessionStorage和localStorage 5M或更多
- 数据有效期不同,sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效, cookie:只在设置的cookie过期时间之前有效
- 作用域不同,sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;localstorage在所有同源窗口中都是共享的;cookie也是在所有同源窗口中都是共享的
9、 数组中常用的方法有哪些?
- forEach 遍历所有的元素
- every 判断所有的元素是否都符合条件
- some 判断是否至少有一个元素符合条件
- sort 排序
- map 对数组中的元素重新组装,生成一个新的数组
- filter 过滤符合条件的元素
10、call,apply,bind的区别
- 相同点
三个函数都会改变this的指向(调用这三个函数的函数内部的this) - 不同点
1、bind会产生新的函数,(把对象和函数绑定死后,产生新的函数)
2、call和apply不会产生新的函数,只是在调用时,绑定一下而已。3
3、call和apply的区别,第一个参数都是要绑定的this,apply第二个参数是数组(是函数的所有参数),call把apply的第二个参数单列出来。
REACT相关
react生命周期
-
getDefaultProps (初始化阶段)
-
getInitialState(获取实例的默认属性)
-
componentWillMount(获取每个实例的初始化状态)
-
render (组件即将被装载、渲染到页面上(多用于根组件中的应用程序配置)
-
componentDidMount 组件在这里生成虚拟的DOM节点
组件真正在被装载之后
在这可以完成所有没有 DOM 就不能做的所有配置,并开始获取所有你需要的数据(发送请求);如果需要设置事件监听,也可以在这完成
- componentWillReceiveProps (组件将要接收到属性的时候调用)
- shouldComponentUpdate(是一个改善性能的地方,组件接受到新属性或者新状态的时候(可以返回false,接收数据后不更新,阻止render调用,后面的函数不会被继续执行了)
- componentWillUpdate
- shouldComponentUpdate
- componentDidUpdate
- componentWillUnmount
react生命周期中,最适合与服务端进行数据交互的是哪个函数?
componentDidMount:在这个阶段,实例和dom已经挂载完成,可以进行相关的dom操作。
(在构造函数中)调用 super(props) 的目的是什么
- 在 super() 被调用之前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。
- 传递 props 给 super() 的原因则是让子类中能用 constructor 访问 this.props。
React 怎么强制更新组件
如果 render() 方法依赖于其他数据,则可以调用 forceUpdate() 强制让组件重新渲染。
调用 forceUpdate() 将致使组件调用 render() 方法,此操作会跳过该组件的 shouldComponentUpdate()。
但其子组件会触发正常的生命周期方法,包括 shouldComponentUpdate() 方法。如果标记发生变化,React 仍将只更新 DOM。
通常你应该避免使用 forceUpdate(),尽量在 render() 中使用 this.props 和 this.state。
Vue和React中key的作用
两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
同一层级的一组节点,他们可以通过唯一的id进行区分。
基于以上这两点假设,使得虚拟DOM的Diff算法的复杂度从O(n^3)降到了O(n)。
当页面的数据发生变化时,Diff算法只会比较同一层级的节点:
如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。
如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。
当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。
所以一句话,key的作用主要是为了高效的更新虚拟DOM。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。
react哪些时候可以设置state 哪些时候不能会(循环)
hooks 为什么不能放在条件判断里
以 setState 为例,在 react 内部,每个组件(Fiber)的 hooks 都是以链表的形式存在 memoizeState 属性中
update 阶段,每次调用 setState,链表就会执行 next 向后移动一步。如果将 setState 写在条件判断中,假设条件判断不成立,没有执行里面的 setState 方法,会导致接下来所有的 setState 的取值出现偏移,从而导致异常发生。
React 高阶组件、Render props、hooks 有什么区别,为什么要不断迭代
这三者是目前react解决代码复用的主要方式:
- 高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。具体而言,高阶组件是参数为组件,返回值为新组件的函数。
- render props是指一种在 React 组件之间使用一个值为函数的 prop 共享代码的简单技术,更具体的说,render prop 是一个用于告知组件需要渲染什么内容的函数 prop。
- 通常,render props 和高阶组件只渲染一个子节点。让 Hook 来服务这个使用场景更加简单。这两种模式仍有用武之地,(例如,一个虚拟滚动条组件或许会有一个 renderltem 属性,或是一个可见的容器组件或许会有它自己的 DOM 结构)。但在大部分场景下,Hook 足够了,并且能够帮助减少嵌套。
React中可以在render访问refs吗?为什么?
<>
<span id="name" ref={this.spanRef}>{this.state.title}</span>
<span>{ this.spanRef.current ? '有值' : '无值' }</span>
</>
//不可以,render 阶段 DOM 还没有生成,无法获取 DOM。DOM 的获取需要在 pre-commit 阶段和 commit 阶段:
state 和 props 区别是啥?
(1)props
props是一个从外部传进组件的参数,主要作为就是从父组件向子组件传递数据,它具有可读性和不变性,只能通过外部组件主动传入新的props来重新渲染子组件,否则子组件的props以及展现形式不会改变。
(2)state
state的主要作用是用于组件保存、控制以及修改自己的状态,它只能在constructor中初始化,它算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的this.setState来修改,修改state属性会导致组件的重新渲染。
(3)区别
props 是传递给组件的(类似于函数的形参),而state 是在组件内被组件自己管理的(类似于在一个函数内声明的变量)。
props 是不可修改的,所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。
state 是在组件中创建的,一般在 constructor中初始化 state。state 是多变的、可以修改,每次setState都异步更新的。
React中发起网络请求应该在哪个生命周期中进行?为什么?
- 跟服务器端渲染(同构)有关系,如果在componentWillMount里面获取数据,fetch data会执行两次,一次在服务器端一次在客户端。在componentDidMount中可以解决这个问题,componentWillMount同样也会render两次。
- 在componentWillMount中fetch data,数据一定在render后才能到达,如果忘记了设置初始状态,用户体验不好。
- react16.0以后,componentWillMount可能会被执行多次。
如何解决 props 层级过深的问题
使用Context API:提供一种组件之间的状态共享,而不必通过显式组件树逐层传递props;
使用Redux等状态库。