JS面试题集锦

175 阅读5分钟

以下面试题摘抄于 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.length Array.isArray() 和 Object.prototype.toString.call() 是最推荐的方法,因为它们能够正确处理所有的边界情况,包括特殊的构造函数和非标准环境。

4、for in和for of的区别

  • 适用的对象不同:
    • for in适用于普通对象、‌数组、‌字符串,尽管for...in可以用于数组,‌但通常不推荐这样做,‌因为它会遍历数组的索引,‌并且可能包括原型链上的属性
    • for of适用于遍历可迭代对象的元素值,‌如数组、‌字符串、‌Map、‌Set、‌TypedArray、‌函数的arguments对象、‌NodeList对象等,不能用于对象
  • 遍历的范围不同:
    • for...in:‌会遍历对象自身以及原型链上的所有可枚举属性
    • for...of:‌一般只遍历对象自身的可枚举属性(‌具体取决于迭代器内部的实现)‌,‌不会遍历原型链上的属性
  • 获取结果不同:
    • for…in 获取的是对象的键名,并且,‌遍历的顺序可能不保证
    • for…of 遍历获取的是对象的键值,并且遍历的顺序是按照可迭代对象的顺序进行的

5、对原型、原型链的理解

  • 原型:在JavaScript中是使用构造函数来创建对象的,每个构造函数都有一个prototype属性,这个属性的值是一个对象,这个对象就是原型对象,原型对象中的属性或方法可以被该构造函数的所有实例共享。
  • 原型链:当访问一个对象的某个属性时,会先在这个对象本身的属性上查找,如果没有找到,则会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,如果还没有找到,就会继续在构造函数的prototype的_proto_中查找,这样一层一层向上查找,直到Object的prototype结束,形成一个链式结构,这就是原型链。

6、如何获得对象非原型链上的属性?

通过hasOwnProperty()方法

hasOwnProperty() 是 JavaScript 中的一个方法,它允许你检查一个对象是否拥有某个特定属性,而这个属性不是继承自其原型链的。如果一个对象拥有一个特定的属性,并且这个属性是直接定义在该对象自身上的,而不是通过继承得到的,hasOwnProperty() 方法将返回 true。如果对象没有这个属性,或者它是通过原型链继承来的,该方法将返回 false。这个方法在检查对象的属性时非常有用,可以确保你操作的是对象自身的属性,而不是可能存在于其原型中的属性。

7、对闭包的理解

闭包是指一个函数有权访问另一个函数作用域中的变量。 创建闭包的常见方式是在一个函数内部创建另一个函数,内部函数可以访问到外部函数的局部变量。

  • 优点:可以避免全局变量污染,设计私有的方法和变量。
  • 缺点:它会常驻内存,增大内存使用量,使用不当很容易造成内存泄漏。

8、什么是事件循环?调用堆栈和任务队列之间有什么区别?

  1. JS是单线程,防止代码阻塞,我们把任务分为:同步任务和异步任务
  2. 同步代码给js引擎执行,异步代码交给宿主环境
  3. 同步代码放入执行栈中,异步代码等待时机成熟送入任务队列排队
  4. 执行栈执行完毕,会去任务队列看是否有异步任务,有就送到执行栈执行,反复循环查看执行,这个过程是事件循环(eventloop)