··写在前面:记录一下最近自己面试的面试题以及答案,用作自己看,如有不对,后续指正更改。(两年经验,主要技术栈react ,小白程序媛👧🏻)··
Q1.介绍一下js的数据类型
- 7 种原始数据类型: Null Undefined String Number Boolean BigInt Symbol
- 引用类型:object,Array,function
如何区分:
- typeof(a) 用于返回值的类型,typeof一元运算符,用来返回操作数类型的字符串。有 "number"、"string"、"boolean"、"null"、"function" 和 "undefined"、"symble"、"object"
typeof(null) //object
typeof(1) //number
typeof(undefiend) //undefiend
------------------------
typeof([]) //object
typeof({}) //object
- instanceof 运算符是用来测试一个对象是否在其原型链原型构造函数的属性。
instanceof 其语法是object instanceof constructor返回布尔值类型
var arr = [1,2,3]; //创建一个数组对象
arr.prototype.constructor = Array; //这一句是系统默认加上的
arr instanceof Array //true
var a={b:"1"}
a instanceof Object //true
let a = function(){}
a instanceof Function //true
Symbol介绍一下:“Symbol” 值表示唯一的标识符。Symbol 保证是唯一的。即使我们创建了许多具有相同描述的 Symbol,它们的值也是不同。描述只是一个标签,不影响任何东西。
Symbol("id")允许创建隐藏属性,不参与for。。。in循环
let id = Symbol("id");
let user = {
name: "John",
age: 30,
[id]: 123
};
for (let key in user) alert(key); // name, age (no symbols)
// 使用 Symbol 任务直接访问
alert( "Direct: " + user[id] );//Direct:123
Object.keys(user) 也会忽略它们。
相反,Object.assign 会同时复制字符串和 symbol 属性:
let id = Symbol("id");
let user = {
[id]: 123
};
let clone = Object.assign({}, user);
alert( clone[id] ); // 123
这里并不矛盾,就是这样设计的。这里的想法是当我们克隆或者合并一个 object 时,通常希望 所有 属性被复制(包括像 id 这样的 Symbol)。
详情可见现代JavaScript教程 https://zh.javascript.info/symbol
Q2: 介绍一下原型和原型链
- js分为函数对象和普通对象,每个对象都有__proto__属性,但是只有函数对象才有prototype属性
- Object、Function都是js内置的函数, 类似的还有我们常用到的Array、RegExp、Date、Boolean、Number、String
- 属性__proto__是一个对象,它有两个属性,constructor和__proto__;
- 原型对象prototype有一个默认的constructor属性,用于记录实例是由哪个构造函数创建;
- Person.prototype.constructor == Person // 准则1:原型对象(即Person.prototype)的constructor指向构造函数本身
- person01.proto == Person.prototype // 准则2:实例(即person01)的__proto__和原型对象指向同一个地方
通过 proto 这个属性,而由这个属性组成的链,就叫做原型链。
原型链的最顶端是 null ,往下是 Object 对象,而且只要是对象或函数类型都会有 proto 这个属性,
原型对象的作用,是用来存放实例中共有的那部份属性、方法,可以大大减少内存消耗。
原型链的作用:
- 实现继承:如果没有原型链,每个对象就都是孤立的,对象间就没有关联,所以原型链就像一颗树干,从而可以实现面对对象中的继承
- 属性查找:首先在当前实例对象上查找,要是没找到,那么沿着 proto 往上查找
- 实例类型判断:判断这个实例是否属于某类对象
Q3:基本数据类型和引用数据类型有什么区别
- 基本类型:存储在栈内存中,因为基本类型的大小是固定,在栈内可以快速查找。
- 引用类型:存储在堆内存中,因为引用类型的大小是不固定的,所以存储在堆内存中,然后栈内存中仅存储堆中的内存地址。
-
基本数据类型:包括:null、undefined、number、string、boolean、symbol(es6)
存放位置:内存中的栈区域中
比较:值的比较,判断是否相等,如果值相等,就相等。一般使用=====进行比较
拷贝:赋值(通过(=)赋值操作符 赋值),赋值完成后,两个变量之间就没有任何关系了,改变其中一个变量的值对另一个没有任何影响 -
引用数据类型:
包括:数组、对象、函数
存放位置:内存的栈区域中存放变量和指针,堆区域存储实际的对象
比较:是引用的比较(就是地址的比较,变量在栈内存中对应的指针地址相等就指向同一个对象)判断是否为同一个对象,示例如下 - 浅拷贝:重新在堆内存中开辟一个空间,拷贝后新对象获得一个独立的基本数据类型数据,和原对象共用一个原对象内的引用类型数据,改变基本类型数据,两个对象互不影响,改变其中一个对象内的引用类型数据,另一个对象会受到影响
- 深拷贝:不论是对象内的基本类型还是引用类型都被完全拷贝,拷贝后两个对象互不影响(JSON.parse(JSON.stringify(obj))
Q3:undefined和null的区别
唉,当时面试心情,
:"空值,未定义"
:"还有呢?"
......
:"没有了"😦
看一下正经答案吧:
null==undefiend///true
null====undefiend//false
null:null类型,代表空值,typeof null 是一个object,可以看作是一个特殊的对象值
undefined:undefined类型,当声明一个变量没有初始化的时候得到的是undefined
null表示"没有对象",即该处不应该有值。典型用法是:
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
参考阮一峰老师链接https://www.ruanyifeng.com/blog/2014/03/undefined-vs-null.html
Q4:介绍一下this:
Q5:介绍一个箭头函数
Q6:介绍一下promise(!!!!!重要)
Q7:setTimout
Q8:宏任务和微任务
Q9:js事件机制
Q10:闭包(!!!!重要)
Q11:跨域,怎么解决
Q12:JSONP怎么实现
Q13:项目优化
Q14:CDN用过吗?说一下
Q15:react:生命周期
Q16:react hooks生命周期
Q17:State是同步还是异步,为啥
Q18:介绍一下redux工作流程
Q19:react 优化性能:SCU,PurComponent,Memo
Q20:hoc高阶组件(--问的时候我都想死,笑死,根本没用过)
Q21:flex布局介绍一下
Q22: if。。else和switch。。case 对比,哪个性能高
Q23:map和forEach区别
Q24:普通函数和箭头函数的区别
Q25:变量提升
Q26:flex布局介绍下
Q27:如何实现垂直居中
Q28:如何实现左右排列
Q29:css实现元素垂直居中。
Q30:React。新旧生命周期对比,分别说出每个生命周期做了什么:
旧版: 挂载:
constructor():完成了React数据的初始化以及实现一些this的绑定。
componentWillMount():
render():渲染组件页面渲染执行的逻辑,render函数把jsx编译为函数并生成虚拟dom,然后通过其diff算法比较更新前后的新旧DOM树,并渲染更改后的节点。
componentDidMount():组件第一次渲染完成时执行的逻辑,此时DOM节点已经生成了。
更新:
componentWillReceiveProps(nextProps):接收父组件新的props时,重新渲染组件执行的逻辑。
shouldComponentUpdate(nextProps,nextState):在setState以后,state发生变化,组件会进入重新渲染的流程时执行的逻辑。在这个生命周期中return false可以阻止组件的更新,主要用于性能优化。
componentWillUpdate (nextProps,nextState):shouldComponentUpdate返回true以后,组件进入重新渲染的流程时执行的逻辑。
render():页面重新渲染
componentDidUpdate(prevProps,prevState):重新渲染后执行的逻辑。
卸载:
componentWillUnmount():组件的卸载前执行的逻辑,比如进行“清除组件中所有的setTimeout、setInterval等计时器”或“移除所有组件中的监听器removeEventListener”等操作。
新版:
挂载:
constructor()
更新:
getDerivedStateFromProps(nextProps, prevState):新的 props 更新到相应的 state 上去。在这个过程中我们实际上是可以访问到当前props的,这样我们可能会对this.props做一些奇奇怪怪的操作,很可能会破坏 state 数据的单一数据源,导致组件状态变得不可预测。
schouldComponetUpdate():
render()
getSnapShotBeforeUpdate()
componentDidUpdata()
卸载:
componentWillUmount()
新旧对比:
使用getDerivedStateFromProps代替了旧的componentWillReceiveProps及componentWillMount。使用getSnapshotBeforeUpdate代替了旧的componentWillUpdate。
Q31:React hooks。生命周期:
useState, useEffect() 和 useLayoutEffect()
Q32:for in 和for of 区别:
for in 取 key;
for of 取 value;
for of 只能用于数组遍历,for in还可以用于对象属性的遍历