学习了一段时间,感觉从面试题里对原理清楚不少,那就检验以下自己,问题来自以下链接:
https://juejin.cn/post/6844903830887366670#heading-20
1 js规定了几种语言类型
string/boolean/number/null/undefined/symbol/object
2 js对象的底层数据结构是什么
不太清楚
3 Symbol类型在实际开发中的应用、可手动实现一个简单的Symbol
应用场景:
- 作为对象的key
- 使用symbol代替常量
- 定义类的私有属性和方法
4 JavaScript中的变量在内存中的具体存储形式
基本类型保存在栈中
引用类型保存在堆中,栈内存中存放该对象的访问地址指向堆内存中的对象
5 null和undefined的区别
undefined表示表里声明过但并未赋值,null表示一个变量将来可能指向一个对象
6 至少可以说出三种判断JavaScript数据类型的方式,以及他们的优缺点,如何准确的判断数组类型
(1)typeof
会将数组、对象、null判断为object
(2)instanceof
可以检测array、object、function
(3)Object.prototype.toString.call()
使用Array.isArray()
7 可能发生隐式类型转换的场景以及转换原则,应如何避免或巧妙应用
- 算术运算符
(1)+
号两边出现字符,结果必然为字符
(2)-、*、/、%将字符转换成数字,再进行正常运算,结果必为数值,如果字符不能转换成数值,会得到NaN,NaN和任何数据做运算结果都是NaN - 比较运算符
<、<=、>、>=、!==、==任意一边出现数值,就会把另一边转成数值,再进行比较 - isNaN()
判断数据能否转换成数值 - 判断语句if()
8 this的原理以及几种不同使用场景的取值
this指向调用函数时的对象
- 普通函数调用,this指向window
- 构造函数调用,this指向实例化的对象
- 匿名函数调用,this指向所处上下文对象的this指向
- 定时器中调用,this指向window
- 对象中的方法调用,this指向该对象
9 理解 JavaScript 的执行上下文栈,可以应用堆栈信息快速定位问题
执行上下文就是js代码被解析和执行时的所处环境。执行上下文共有三种类型:全局执行上下文、函数执行上下文、Eval函数上下文
10 理解堆栈溢出和内存泄漏的原理,如何防止
js中数据存储分为栈和堆,栈遵循先进后出的原则,一旦进栈过多就会导致栈满,一般出现在递归中,解决方式为将递归变为循环
内存泄漏:申请的内存执行完之后没有及时地清理和销毁,占用内存且不能回收。解决方法为减少不必要地全局变量,使用严格模式来避免创建意外的全局变量,使用完数据后,及时解除引用。
11 理解模块化解决的实际问题
模块化
:模块化就是把系统分离成独立功能的方法,这样需要什么功能就加载什么功能
主要解决两个问题:
- 命名冲突
- 文件依赖
12 为何try里面放return,finally还会执行,理解其内部机制
在try和catch中,如果碰到return语句中,会在return之前,先执行finally中的内容,如果finally有return,那么就直接return了
13 使用Promise实现串行
function myPromise(_promises){
return _promises.reduce((prev,next)=>prev.then(()=>next()),Promise.resolve())
}
async function myPromise(_promises){
for(let p of _promises){
await p()
}
}
12 如何在保证页面运行流畅的情况下处理海量数据
对于一次性插入大量数据,一般有两种做法:
- 时间分片
- 虚拟列表
requestAnimationFrame是由系统决定回调函数的执行时机
let ul=document.getEementById('container')
let total=100000
let once=20
let page=total/once
let index=0
function loop(curTotal,curIndex){
if(curTotal<=0){
return false
}
let pageCount=Math.min(curTotal,once)
window.requestAnimationFrame(function(){
for(let i=0;i<pageCount;i++){
let li=document.createElement('li')
li.innerText=curIndex+i+':'+~~(Math.random()*total)
}
loop(curTotal-pageCount,curIndex+pageCount)
})
}
loop(total,index)
进一步优化:DocumentFragment
DocumentFragment不是真实DOM树的一部分,它的变化不会触发DOM树的重新渲染,且不会导致性能问题
let ul=document.getElementById('container')
let total=10000
let once=20
let page=total/once
let index=0
function loop(curTotal,curIndex){
if(curTotal<=0)return false
let pageCount=Math.min(curTotal,once)
window.requestAnimationFrame(function(){
let fragment=document.createDocumentFragment()
for(let i=0;i<pageCount;i++){
let li=document.createElement('li')
li.innerText=''+curIndex
fragment.appendChild(li)
}
ul.appendChild(fragment)
loop(curTotal-pageCount,curIndex+pageCount)
})
}
13 理解ECMAScript和JavaScript的关系
ECMAScript是js的标准,js包括三个部分:
- ECMAScript,提供核心语言功能
- 文档对象DOM,提供访问和操作网页内容的方法和接口
- 浏览器对象BOM,提供与浏览器交互的方法和接口
14 熟练掌握JavaScript提供的全局对象
(1)JSON对象方法
JSON.parse()
:解析字符串并返回对应的值JSON.stringify()
:将一个js对象转换成JSON字符串
(2)Object
Object.create()
:创建一个新对象,使用现有的对象提供新创建对象的__proto__Object.defineProperties()
:在一个对象上定义新的属性或修改现有属性,并返回该对象Object.assign(target,...sources)
:将所有source对象属性合并到target中,并返回target
(3)Date
getDate()
:返回Date对象为一个月中的哪一日getDay()
:返回Date对象为一周中的第几天getFullYear()
:返回一个Date对象的完整年份
(4)Math
Math.trunc()
:返回一个数的整数部分
(5)encodeURI、decodeURI
encodeURI
:给URI编码decodeURI
:给URI解码
15 setInterval需要注意的点,使用settimeout实现setInterval
setInternal不能传递带参数的函数,需要使用clearInternal清楚定时器
function mySetInternal(fn,time){
function internal(){
setTimeout(internal,time)
fn()
}
setTimeout(internal,time)
}