目录
ES6介绍
ES6,ECMAScript 6.0,就是javascript的新标准,属于是这里面的东西好多都用过,但我不知道这是不是ES6的。
问题+回答
ES6新特性有哪些
- let和const
- class语法糖
- symbol数据类型
- 箭头函数
- 扩展运算符(…)
- 生成器(Generator)和遍历器(Iterator)
- import/export
- 解构赋值
- set和map数据类型
什么是闭包
就是定义在函数内部能够读取其他函数内部变量的函数
优点:
1.保护函数内的变量安全
2.在内存中维持一个变量(用的太多就变成了缺点,占内存) ;
3. 逻辑连续,当闭包作为另一个函数调用的参数时,避免你脱离当前逻辑而单独编写额外逻辑。
4. 方便调用上下文的局部变量。
5. 加强封装性,可以达到对变量的保护作用。
缺点:
1.常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
2.还有有一个非常严重的问题,那就是内存浪费问题,这个内存浪费不仅仅因为它常驻内存,更重要的是,对闭包的使用不当会造成无效内存的产生。
什么是冒泡(不是冒泡排序的冒泡)
由里往外,比如下面代码中如果不阻止冒泡点击fn2就会触发fn1
<div onclick="fn1">
<div onclick="fn2">
xxxxx
</div>
</div>
addEventListener的第三个参数就默认是false,不阻止冒泡
相反的由外往里叫捕获
call,apply,bind是干什么的,有什么区别
-
共同点:
- 调用函数并改变this指向 区别
- fun.call(this指向,函数调用的参数1,函数调用的参数2)
- fun.apply(this指向,[函数调用的参数1,函数调用的参数2])第二个参数必须是数组
-
fun.bind(this指向)(函数调用的参数1,函数调用的参数2) bind不能立即执行,因为它返回的是一个函数,必须要fun.bind()()才能执行
(Bind可以用来改变click事件绑定的函数(不用立即执行))
new做了哪些事
- 创建空对象
- 执行constructor创建实例
- 判断对象是否存在且是对象或者函数
- 依据判断结果返回对象或者实例
什么是宏任务和微任务,以及以什么顺序执行
说到宏任务和微任务首先要了解事件循环机制,
-
事件循环
- js是单线程的,但是总要执行一些异步指令,那就只能靠事件循环,可以理解为:
- 解析js的时候一直循环解析,当遇到 同步代码放入执行队列依次执行,遇到异步代码分为宏任务队列和微任务队列,同步代码执行完先执行 微任务,等微任务队列全部执行完执行 宏任务。
**同步代码:**立刻执行的都是同步代码,比如console.log。要注意promise在then前都属于同步代码
微任务:.then,catch,async/await
宏任务: setTimeout等计时器
localStorsge,sessionStorage,cookies的区别
- 当浏览器关闭时local还有,session消失
- Cookies可以设置过期时间expires
- Cookie不能超过4k,storage不能超过5m(浏览器不同存储大小不同
filter和find的区别
filter和find都是不改变原数组的方法,
区别是find返回第一个查找到的元素,filter返回一个满足条件的数组
深拷贝和浅拷贝
首先要介绍一下什么是深拷贝和浅拷贝,
浅拷贝: 学过c语言的都知道指针,指针指向的是地址,而js中的引用数据类型(object,array)存储的就是地址,就可以把它想象成指针,指针赋值说明什么,说明赋值只是存了个地址,那么地址里的值变了,指针指向的内容也会改变,这就是浅拷贝,也就是不够深,不够彻底的拷贝;
深拷贝: 那深拷贝是什么呢,深拷贝就是赋值之后原数据再怎么改都不会影响赋值的数据。
那么哪些赋值方法是深拷贝那些是浅拷贝呢
-
浅拷贝:
- obj1=obj
- Object.assign(obj1,obj) 深拷贝:
- obj = {a:1,b:2}
- obj2 = JSON.parse(JSON.stringify(obj1))
堆区和栈区:
堆区:动态分配的内存,引用数据类型栈区存放的指针指向堆区
栈区:自动分配的内存
Document.write和innerHtml的区别:
document.write只能重绘整个页面,
innerHTML可以重绘页面的一部分
Generator:
Generator函数使用yield+next() 可以返回多次值
function* gen() {
yield 1
yield 2
return 3
yield 4
}
let g = gen();
console.log(g.next()) // {value: 1, done: false}
console.log(g.next()) // {value: 2, done: false}
console.log(g.next()) // {value: 3, done: true}
console.log(g.next()) // {value: undefined, done: true}
可以循环遍历generator,for foo of gen
但是return不会被遍历到也不会被扩展运算符显示到
注意:next里可以放参数,相当于给上一个yield赋值,yield本身结果并不是值,而是undefined,第一个next是没有形参的,给了也没有用
类型判断
console.log('------------类型判断------------')
console.log([1,2,3]==[1,2,3]) //false
console.log({}=={}) //false,里面有也是false
//这两种都是引用类型的比较,比较的是指针
console.log(typeof Number === typeof Window) //true 都是function
console.log(typeof window) //object
console.log(typeof Number()) //number
console.log("------------instanceof-----------")
console.log(2 instanceof Number) //false ,因为instance只能用来判断引用数据
console.log([] instanceof Array) //true
console.log(function(){} instanceof Function) //true ,注意这个function的typeof也是function
// instance运算符原理:判断构造函数的prototype属性是否在对象原型链上的任何位置
console.log("------------constructor-----------")
console.log((2).construtor===Number) //true,注意这里的2外面有括号,因为原始数据类型不能用xxx.constructor
console.log("------------Object方法-----------")
var a = Object.prototype.toString
console.log(a.call(2)) //[object Number]
console.log(a.call(null)) //[object Null]
console.log(a.call({})) //[oject Object]
object.is和 === 和 ==的区别
object.is()与===的区别:is()中+0和-0不等,NaN和NaN相等
===不仅判断值还判断类型,==如果类型不同会进行类型强转