1.js有哪些数据类型
基础数据类型:string,number,boolean,null,undefined,bigInt,symbol
引用数据类型:Object
2.js检测数据类型的方式
- typeof:其中数组、对象、null都会被判断为object,其他判断都正确
- instanceof:只能正确判断引用数据类型,而不能判断基本数据类型。
instanceof
运算符可以用来测试一个对象在其原型链中是否存在一个构造函数的prototype
属性。 - constructor:console.log((2).constructor === Number); // true
constructor
有两个作用,一是判断数据的类型,二是对象实例通过constrcutor
对象访问它的构造函数。需要注意,如果创建一个对象来改变它的原型,constructor
就不能用来判断数据类型了 - Object.prototype.toString.call(),使用 Object 对象的原型方法 toString 来判断数据类型
3.如何判断是否为数组
- Object.prototype.toString.call()
- 通过原型链做判断,obj.__proto__ === Array.prototype
- 通过ES6的Array.isArray()方法
- instanceof做判断,obj instanceof Array
- Array.prototype.isPrototypeOf(obj)
4.原型和原型链
- 首先prototype是原型,_proto_是原型链。
- 每个构造函数都有一个prototype原型对象,prototype原型对象里的constructor指向构造函数。
- 构造函数new出的对象通过_proto_指向prototype原型对象,在prototype中的多个prototype一层一层查找看有没有目标元素,就是原型链。
- 原型链的顶点是Object.prototype。
5.call apply bind区别
- call第一个参数是对象,后面可以接受若干个参数
- apply第一个参数是对象,后面是用数组提供参数
- call apply直接调用,bind会创建一个新函数,将第一个参数作为它运行时的this
6.new操作符具体干了什么
- 创建一个新的空对象
- 将这个新对象的原型指向构造函数的原型
- 将构造函数的this指向这个新对象
- 执行构造函数代码,初始化新对象
- 返回新对象
7.节流防抖
节流:函数执行一次后,在规定的时间内不再执行
防抖:在规定的时间内没有触发事件,就执行函数,如果在规定的时间触发了时间久重新开始计时
8.promise有哪些方法
- promise.all是等待所有异步方法执行完成后再继续后面的操作。
- promise.race是哪一个方法最先执行结束就返回哪个方法的执行结果。
- promise.allSettled是无论请求对错最终都会返回一个数组对象 到 .then 中,并切返回的数据中标识了错误跟正确数据 。
- promise.finally是不管成功或者失败都会执行回调函数。
- promise.any是返回第一个成功的值,如果全部都被拒绝了,就返回第一个拒绝的。
9.哪些操作会造成内存泄漏
- 闭包
- 意外的全局变量
- 没有清理的dom元素引用
- 被遗忘的定时器或者回调
10.js请求会有哪些缓存
- dns缓存
- cdn缓存
- 浏览器缓存
- 服务器缓存
11.为什么0.1+0.2不等于0.3
12.如何跳出forEach循环
forEach
是数组的一种迭代方法,主要用于对数组中的每一项执行给定的函数。它只是简单地对数组进行遍历,没有提供跳出循环的机制。
- 使用
every
或 some方法遍历。every
方法测试数组中的每一元素是否都满足所提供的测试函数。如果有任一元素不满足条件,则整个方法返回false
并且立即终止进一步的遍历。some
方法与every
相反,它检查数组中是否至少有一个元素满足测试函数。如果找到了一个满足条件的元素,则方法返回true
并且停止遍历。 -
通过抛出异常退出。当异常被抛出时,正常的流程被打断,可以通过
catch
块捕获异常,从而实现停止迭代的效果。 -
除了
every
和some
,还可以使用传统的for
循环或for...of
循环替代forEach
,这样就可以使用break
来退出循环。
13.事件循环机制
可参考:https://article.juejin.cn/post/7231986666511237175
执行顺序:同步代码->微任务->宏任务
题目:
Promise.resolve().then(() => {console.log(0);return Promise.resolve(4);}).then((res) => {console.log(res);});
Promise.resolve().then(() => {console.log(1);}).then(() => {console.log(2);}).then(() => {console.log(3);}).then(() => {console.log(5);}).then(() => {console.log(6);});
结果:0123456
14.箭头函数与普通函数有什么区别
- 箭头函数比普通函数更加简洁
- 箭头函数没有自己的this
- 箭头函数继承来的this指向永远不会改变,指向最近的外层作用域中的this所指对象
- call()、apply()、bind()等方法不能改变箭头函数中this的指向
- 箭头函数不能作为构造函数使用
15.ES6有哪些新特性
- 箭头函数
- 解构赋值
- 模板字符串
- promise
- symbol Symbol是ES6中引入的一种新的基本数据类型,用于表示一个独一无二的值,不能与其他数据类型进行运算
- 新的变量声明方式-let和const
- 模块化-es6新增了模块化,根据功能封装模块,通过import导入,然后通过export导出也可以使用export default导出
- for…of 循环,用于遍历可迭代对象(如数组、Map 和 Set)中的元素
- 扩展运算符:使用 ... 可以将数组或对象展开成多个参数,或者将多个参数合并成一个数组
- 展开运算符:在ES6中用...来表示展开运算符,它可以将数组或者对象进行展开
- Map 和 Set,引入了两种新的数据结构,分别用于存储键值对和唯一值
- Proxy,允许在对象和函数调用等操作前后添加自定义的行为
- 类(Class),引入了面向对象编程中类的概念
16.说说你对闭包的理解
- 是什么 当一个函数中的内部函数被拿到函数外部调用,又因为在js中内层作用域总是能访问外层作用域的,那么内部函数存在对外部函数中变量的引用,这些变量的集合称之为闭包
- 使用场景:
- 创建私有变量 (全局变量不易维护)
- 延长变量的生命周期
- 实现柯里化
- 缺点:会造成内存泄漏
17.如何判断两个对象是否相等
JSON.stringify()将对象
转化为字符串使用===
操作符进行比较- 使用遍历递归进行比较
- 使用 Lodash 的 isEqual 方法
- 使用 Object.is() 方法,console.log(Object.is(obj1, obj2)); //true
18.数组去重
- 使用filter()方法
const arr = [1, 2, 3, 4, 2, 3, 5]; const uniqueArr = arr.filter((item, index) => arr.indexOf(item) === index); console.log(uniqueArr); // [1, 2, 3, 4, 5]
- 使用reduce()和include()方法
const arr = [1, 2, 3, 4, 2, 3, 5]; const uniqueArr = arr.reduce((prev, cur) => prev.includes(cur) ? prev : [...prev, cur], []); console.log(uniqueArr); // [1, 2, 3, 4, 5]
- Set方法,...new Set(arr)
19.import与require区别
- import(es6)编译时加载
- require(commonjs)运行时加载