记一次比较遥远的面试提问,记得多少写多少,附较详细的解答,欢迎指出错误。
1. 说说CSS中的相对定位与绝对定位:
position: relative;
为相对定位,根据自身位置来进行定位。position: absolute;
为绝对定位,若父级节点的position
属性不为static
,则根据父级节点位置进行定位;否则则继续寻找上一级position
属性不为static
的节点进行定位,若都没有找到,则以视窗进行定位。
2. this
的指向
- 一般情况下,
this
指向调用该函数的对象 - 箭头函数里的
this
指向定义时所在的对象 this
的指向可以通过bind
函数改变
3. 类里静态方法的this
指向
因this
指向调用该函数的对象,而静态方法不用创建实例来调用,而是通过类本身来直接调用,故this
指向这个类本身而不是实例。
4. let
、const
let
:
- 定义的变量只在当前代码块有效,存在局部作用域。
- 不存在变量提升,即未定义前访问变量会报错,而不是返回
undefined
。 - 在同一个代码块内不允许重复定义同一个变量。
const
:
- 拥有
let
的所有特性 const
定义的常量指向的地址不能改变。- 如果定义的是个对象或者数组这种引用类型,只是不能改变它指向的内存地址,但它的属性可以改变。
5. 在React组件的render函数里调用setState会发生什么问题?哪个生命周期函数可以阻止这个问题发生?PureCompoent。
会发生死循环问题,因为setState
又会触发render
函数。shouldComponentUpdate
生命周期函数返回false
的时候不会触发render
,可以阻止这个问题发生。
PureCompoent在shouldComponentUpdate
实现一个浅比较,需要注意的是以下代码不会触发render
:
const newState = this.state.someState;
newState.attr = 'newValue';
this.setState({
someState: newState,
});
这是因为浅比较是比较这个变量的地址,地址不变则返回false
。
下面代码会触发render
:
const newState = this.state.someState;
newState.attr = 'newValue';
this.setState({
someState: {...newState},
});
还可以使用immutable来写,这里使用的是immutable的一个辅助库immutability-helper-x:
import update from 'immutability-helper-x';
...
this.setState({
someState: update.$set(this.state.someState, 'attr', 'newValue'),
});
6. 浅拷贝和深拷贝。
浅拷贝
浅拷贝就是把对象的属性的值都复制一份到新的内存地址,但只复制一层,若属性的值为对象,则还是原来的引用。如:
const obj = {
child: {
key: 'value',
},
};
const newObj = shallowCopy(obj);
console.log(newObj.child === obj.child); // true
实现方法:
function shallowCopy(obj) {
// ES6
// return {...obj};
return Object.assign({}, obj);
}
深拷贝
而深拷贝则遍历整个对象,把这个对象所有的值都移到新的内存空间,不存在原来的引用,如:
const obj = {
child: {
key: 'value',
},
};
const newObj = deepCopy(obj);
console.log(newObj.child === obj.child); // false
深拷贝可以通过遍历整个对象来拷贝,也有一种比较简单的实现方法,但效率都比较差。
function deepCopy(obj) {
return JSON.parse(JSON.stringify(obj));
}
7. Node中的事件循环
因为JS是单线程的,执行I/O操作时会阻塞线程,如果一直等待I/O操作完成再执行下面的代码是不现实的,因此就需要事件循环。
事件循环就是当遇到像I/O这种阻塞线程的操作时,把他们交给系统内核去进行处理,Node继续往下执行代码,等到I/O操作执行完后告知Node,然后Node会把响应的回调函数加进事件队列等待执行。
8. 浏览器缓存
强缓存
HTTP状态码为200(from cache)
,它的优点是没有访问服务器,直接在本地读取缓存,减少HTTP请求,但也因为如此,这也是它的缺点,因为它不知道服务器资源是否有更新,从而无法获取到最新的资源,这个问题通常用给静态资源添加Hash值来判断资源有无更新,若Hash值不同,则会请求获取最新资源。
相关Header有(按优先级排序):
Cache-Control
。设定一个最大有效期,如Cache-Control: max-age=36000000
Expires
。它描述一个最后的过期时间,如Expires: Tue, 17 Jul 2018 15:42:01 GMT
协商缓存
HTTP状态码为304
,当没有强缓存或者强缓存过期时,会发送请求到服务器,若服务器发现资源没有更新,则返回304
告诉客户端不必更新。因为它还是要发送请求,所以比强缓存慢。
相关Header有:
Last-Modified
、If-Modified-Since
ETag
、If-None-Match
9. 内存泄漏
JS提供自动管理内存,称为“垃圾回收机制”,通常用的是“引用计数”,即当一个对象的引用数为0时就把它释放回收。而当一个不在使用的对象的引用数又不为0的时候,无法把他进行回收,即造成内存泄漏问题。