五年面试,三年模拟(js篇)
构造函数的new都做了些什么
- JS内部首先会先生成一个对象;
- 再把函数中的this指向该对象;
- 然后执行构造函数中的语句;
- 最终返回该对象实例。
什么是promise
Promise 是一个允许我们处理异步操作的对象。
promise有哪些类方法
- promise.all并行执行多个promise,所有传参的promise的resolve 回调都结束才会执行resolve回调,反之执行reject需要用catch捕获
- promise.race返回第一个resolve的promise,剩下的promise哪怕成功resolve了也不会返回
promise的链式调用是怎么实现的
因为then方法会返回一个新的Promise。这个新的Promise会根据它接收的参数来决定状态, 如果接收到的不是一个Promise, 那么它就自动置为Fullfilled, 如果接收到的参数是Promise, 那么就将它的resolve函数放在接收到的Promise中的then方法执行。
js中有哪几种数据类型
最简单的问题,不过遇到还是经常漏答
一共有8种数据类型:String、Number、Boolean、Null、Undefined、Object、Symbol、BigInt.
8种数据类型又可以分为基本类型和引用类型,Object为引用类型,其余均为基本类型.
ps:Object类型中有数组(Array)、函数(Function)以及两个特殊的对象:正则(RegExp)和日期(Date)
pps: 基本类型存放在栈中,引用类型存放在堆内存中
let、var和const的区别
1.var 声明的变量,在全局范围内都有效,let 和 const 声明的,只在它所在的代码块内有效
2.let 和 const 声明的变量不存在变量提升现象(var 定义变量可以先使用,后声明)
3.let 不允许在相同的作用域内重复声明同一个变量(const声明对象时必须赋值,且值不允许改变,也不能在同一个作用域重复声明)
4.const 在声明时必须初始化赋值,一旦声明,其声明的值就不允许改变,更不允许重复声明
箭头函数和普通函数的区别
1.this指向不同,普通函数的this指向直接调用者,没有直接调用者,this指向window;箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this
2.箭头函数没有 arguments 对象
数组的pop()和unshift()区别
这么基础的问题…我竟然答错了
pop()删除数组的最后一个元素,并返回新数组;unshift()向数组前追加内容
如何理解闭包
闭包简单来说就是函数嵌套函数(结构如下),内部函数引用来自外部函数的变量,从而导致垃圾回收机制没有把当前变量回收掉。
1 |
|
闭包的使用场景:ajax请求成功后的回调、防抖和节流
闭包的缺点:内存泄漏
解决方法:将闭包引用的外部函数中活动对象清除
如果有a,b,c三个函数,c的传参需要a和b返回的结果,如何处理
下意识的回答就是写在回调里面,不过面试官肯定不是想听到这个回答
使用promise.all
1 |
|
null、undefined和nan区别
1.null表示”没有对象”,即该处不应该有值
2.undefined表示”缺少值”,就是此处应该有一个值,但是还没有定义(变量被声明了,但没有赋值时,就等于undefined)
3.nan表示不是一个数字
== 和 === 的区别以及新增的 Object.is
==
抽象相等,比较时,会先进行隐式强制类型转换,然后再比较值
===
严格相等,会比较两个值的类型和值
ps:es6中新增了一个新的方法Object.is()
来比较两个值严格相等,它与严格比较运算符(===)基本一致,不同之处只有两个:一是+0不等于-0,二是NaN等于自身。
arguments对象是不是数组?以及如何转成数组
1 |
|
arguments对象转成数组的几种方法
1 |
|
常见的解决跨域的方法
跨域的产生是因为浏览器的’同源策略’,即协议、域名、端口有任何一个不同都会被当成不同的域,然后ajax请求就会失败
1 |
|
请简述JavaScript中的this
js中this关键字表示当前对象的一个引用
简述javascript中this的指向
1.this永远指向函数运行时所在的对象
2.普通的函数调用,this指向调用对象
3.构造函数,如果不用new操作符而直接调用,那即this指向window。用new操作符生成对象实例后,this就指向了新生成的对象
for…of和for…in区别
for…of是es6新增的遍历数组和对象的方法
1.for…of输出的是value,for…in输出的是key
2.for…of遍历不可迭代对象(普通对象)时会报错,for…in则可以正常输出key
3.for…in更适合遍历对象,for…of适合数组
4.for…in遍历的是对象的可枚举属性,包括对象自身及从原型链继承而来的属性;for…of遍历的是可迭代属性
什么是事件委托/事件代理?
将本该绑定在多个子元素上的事件绑定到他们的祖先元素上,尤其是在动态添加子元素的时候,可以非常方便的提高程序性能,减小内存空间
什么是事件冒泡?以及如何阻止冒泡?
当某个元素的某类型事件被触发时,那么它的父元素同类型的事件也会被触发,一直触发到根源上。
如何阻止事件冒泡?调用当前事件对象的stopPropagation()方法
1 |
|
防抖和节流的原理
防抖和节流的原理都是利用了闭包。
防抖的原理是使用了闭包,通过不断地记录新的定时器与清除旧的定时器,达到函数调用不断延迟,且仅调用一次的效果。
节流的原理也是使用了闭包,记录了开始时间start及每一次触发时间curr,两变量相减得到差值,当插值大于节流分片的时间时,可执行函数,同时更新start。另外通过setTImeout防止函数持续触发时间太短,没有调用函数,对于定时器也有所每次清除。
什么是原型和原型链
什么是原型?
每个函数对象都会有一个prototype属性, 叫做原型.
什么是原型链?
查找对象属性的过程。(常说的原型链条就是 [[prototype]]链 或者 __proto__链.)
假设要查询对象o的属性x,如果o中不存在x,那么将会继续在o的原型对象中查询属性x。如果原型对象中也没有x,但这个原型对象也有原型,那么继续在这个原型对象的原型上执行查询,直到找到x或者查找到一个原型是null的对象为止。可以看到,对象的原型属性构成了一个”链”,通过这个”链”可以实现属性的继承。
深拷贝与浅拷贝的区别
浅拷贝是复制,两个对象指向同一个地址;
深拷贝是新开栈,两个对象指向不同的地址
ps:Object.assign的拷贝,是对于第一层属性的拷贝,所以是浅拷贝。
堆栈区别
在js中,每一个数据都需要一个内存空间。内存空间又被分为两种,栈内存(stack)与堆内存(heap)。
1.栈内存一般储存基础数据类型;堆内存一般储存引用数据类型
2.栈会自动分配内存空间,会自动释放;堆动态分配内存,大小不定也不会自动释放
localStorage、sessionStorage和cookie区别
特性 | Cookie | localStorage | sessionStorage |
---|---|---|---|
数据的生命期 | 一般由服务器生成,可设置失效时间。如果在浏览器端生成Cookie,默认是关闭浏览器后失效 | 除非被清除,否则永久保存 | 仅在当前会话下有效,关闭页面或浏览器后被清除 |
存放数据大小 | 4k左右 | 一般为5MB | 一般为5MB |
与服务器端通信 | 每次都会携带在HTTP头中 | 不参与和服务器的通信 | 不参与和服务器的通信 |
比较两个javaScript对象是否相等
1 |
|
oninput和onchange区别
1.只有input和textarea元素才有oninput事件;而onchange可以用于input、select和textarea元素
2.input的onchange事件需要失去焦点才会触发(当鼠标在其他地方点一下才会触发);oninput事件在用户输入时触发,它是在元素值发生变化时立即触发
如何判断一个对象是否是数组
1 |
|
++i 和 i++ 区别
1 |
|
使用i++时,i先将自身的值赋值给变量a,然后再自增1
使用++i时,i先将自身的值自增1,再将自增后的值赋值给变量a
在函数定义前输出函数会输出啥?
1 |
|
换一种写法
1 |
|
为什么会这样,因为仅仅是将声明提升了,赋值操作并没有提升