以下面试题摘抄于 juejin.cn/post/733006… 部分面试题答案有所整理与更改
1、js数据类型有哪些及它们的区别
- 基本数据类型:number、string、boolean、null、undefined、symbol、BigInt
- 引用数据类型:
- Object:包括数组、函数和用户自定义的类型。
- Array:用于处理有序的元素集合。
- Function:在JavaScript中,函数也是对象,因此属于引用类型。
区别:
- 基本数据类型是在栈内存中,值引用,对原始类型的操作不会改变其原始值,而是会创建一个新的值。
- 引用数据类型则是在堆内存中,地址引用,并且是可变的。。
PS:
- NAN属于number数据类型
- Symbol 代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题。
- BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。
2、 数据类型检测的方式有哪些
- typeof 检测基本数据类型(除了null),object、array、date、regExp、null 都会返回object
console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof 'str'); // string
console.log(typeof []); // object
console.log(typeof function(){}); // function
console.log(typeof {}); // object
console.log(typeof undefined); // undefined
console.log(typeof null); // object
- intanceof 检测引用数据类型,其内部运行机制是判断在其原型链中能否找到该类型的原型
console.log(2 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log('str' instanceof String); // false
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log({} instanceof Object); // true
- constructor 检测所有数据类型(除了null,undefined),但是如果创建一个对象来改变它的原型,
constructor就不能用来判断数据类型了
console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true
- Object.prototype.toString.call 检测所有数据类型
var a = Object.prototype.toString;
console.log(a.call(2));
console.log(a.call(true));
console.log(a.call('str'));
console.log(a.call([]));
console.log(a.call(function(){}));
console.log(a.call({}));
console.log(a.call(undefined));
console.log(a.call(null));
3、判断数组的方式有哪些
- Object.prototype.toString.call(): Object.prototype.toString.call(arr) === '[object Array]'
- Array.isArray(): 判断一个变量是否是数组
- intanceof: 检查一个对象是否是特定构造函数的实例。
- constructor: arr.constructor === Array
- 通过
length属性: 如果数组有length属性,并且该属性值为正整数,则可以认为它是数组。arr.length >= 0 && (arr.length >>> 0) === arr.lengthArray.isArray()和Object.prototype.toString.call()是最推荐的方法,因为它们能够正确处理所有的边界情况,包括特殊的构造函数和非标准环境。
4、for in和for of的区别
- 适用的对象不同:
- for in适用于普通对象、数组、字符串,尽管
for...in可以用于数组,但通常不推荐这样做,因为它会遍历数组的索引,并且可能包括原型链上的属性 - for of适用于遍历可迭代对象的元素值,如数组、字符串、Map、Set、TypedArray、函数的arguments对象、NodeList对象等,不能用于对象
- for in适用于普通对象、数组、字符串,尽管
- 遍历的范围不同:
for...in:会遍历对象自身以及原型链上的所有可枚举属性for...of:一般只遍历对象自身的可枚举属性(具体取决于迭代器内部的实现),不会遍历原型链上的属性
- 获取结果不同:
- for…in 获取的是对象的键名,并且,遍历的顺序可能不保证
- for…of 遍历获取的是对象的键值,并且遍历的顺序是按照可迭代对象的顺序进行的
5、对原型、原型链的理解
- 原型:在JavaScript中是使用构造函数来创建对象的,每个构造函数都有一个prototype属性,这个属性的值是一个对象,这个对象就是原型对象,原型对象中的属性或方法可以被该构造函数的所有实例共享。
- 原型链:当访问一个对象的某个属性时,会先在这个对象本身的属性上查找,如果没有找到,则会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,如果还没有找到,就会继续在构造函数的prototype的_proto_中查找,这样一层一层向上查找,直到Object的prototype结束,形成一个链式结构,这就是原型链。
6、如何获得对象非原型链上的属性?
通过hasOwnProperty()方法
hasOwnProperty() 是 JavaScript 中的一个方法,它允许你检查一个对象是否拥有某个特定属性,而这个属性不是继承自其原型链的。如果一个对象拥有一个特定的属性,并且这个属性是直接定义在该对象自身上的,而不是通过继承得到的,hasOwnProperty() 方法将返回 true。如果对象没有这个属性,或者它是通过原型链继承来的,该方法将返回 false。这个方法在检查对象的属性时非常有用,可以确保你操作的是对象自身的属性,而不是可能存在于其原型中的属性。
7、对闭包的理解
闭包是指一个函数有权访问另一个函数作用域中的变量。 创建闭包的常见方式是在一个函数内部创建另一个函数,内部函数可以访问到外部函数的局部变量。
- 优点:可以避免全局变量污染,设计私有的方法和变量。
- 缺点:它会常驻内存,增大内存使用量,使用不当很容易造成内存泄漏。
8、什么是事件循环?调用堆栈和任务队列之间有什么区别?
- JS是单线程,防止代码阻塞,我们把任务分为:同步任务和异步任务
- 同步代码给js引擎执行,异步代码交给宿主环境
- 同步代码放入执行栈中,异步代码等待时机成熟送入任务队列排队
- 执行栈执行完毕,会去任务队列看是否有异步任务,有就送到执行栈执行,反复循环查看执行,这个过程是事件循环(eventloop)