2023年前端面试汇总 - JavaScript

2023年前端面试汇总 - JavaScript_第1张图片

1. 数据类型

1.1. JavaScript有哪些数据类型,它们的区别?

JavaScript共有八种数据类型,分别是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。

其中 Symbol 和 BigInt 是ES6 中新增的数据类型:

Symbol 代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题。

BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。

这些数据可以分为原始数据类型和引用数据类型:

栈:原始数据类型(Undefined、Null、Boolean、Number、String)

堆:引用数据类型(对象、数组和函数)

两种类型的区别在于存储位置的不同:

原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;

引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

堆和栈的概念存在于数据结构和操作系统内存中,在数据结构中:

在数据结构中,栈中数据的存取方式为先进后出。

堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。

在操作系统中,内存被分为栈区和堆区:

栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等,其操作方式类似于数据结构中的栈。

堆区内存一般由开发着分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。

1.2. 数据类型检测的方式有哪些?

1.2.1. typeof

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

其中数组、对象、null都会被判断为object,其他判断都正确。

1.2.2. instanceof

instanceof可以正确判断对象的类型,其内部运行机制是判断在其原型链中能否找到该类型的原型。

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

可以看到,instanceof 只能正确判断引用数据类型,而不能判断基本数据类型。instanceof 运算符可以用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。

1.2.3. 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

constructor有两个作用,一是判断数据的类型,二是对象实例通过 constrcutor 对象访问它的构造函数。需要注意,如果创建一个对象来改变它的原型,constructor就不能用来判断数据类型了:

function Fn(){};
 
Fn.prototype = new Array();
 
var f = new Fn();
 
console.log(f.constructor===Fn);    // false
console.log(f.constructor===Array); // true

1.2.4. Object.prototype.toString.call()

Object.prototype.toString.call() 使用 Object 对象的原型方法 toString 来判断数据类型:

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));

同样是检测对象obj调用toString方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样,这是为什么?

这是因为toString是Object的原型方法,而Array、function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串…),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object原型上的toString方法。

1.3. 判断数组的方式有哪些?

1.4. null和undefined区别?

1.5. typeof null 的结果是什么,为什么?

1.6. intanceof 操作符的实现原理及实现

1.7. 为什么0.1+0.2 ! == 0.3,如何让其相等

1.8. 如何获取安全的 undefined 值?

1.9. typeof NaN 的结果是什么?

1.10. isNaN 和 Number.isNaN 函数的区别?

1.11. == 操作符的强制类型转换规则?

1.12. 其他值到字符串的转换规则?

1.13. 其他值到数字值的转换规则?

1.14. 其他值到布尔类型的值的转换规则?

1.15. || 和 && 操作符的返回值?

1.16. Object.is() 与比较操作符 "=","" 的区别?

1.17. 什么是 JavaScript 中的包装类型?

1.18. JavaScript 中如何进行隐式类型转换?

1.19. +操作符什么时候用于字符串的拼接?

1.20. 为什么会有Bigint的提案?

1.21. object.assign和扩展运算法是深拷贝还是浅拷贝,两者有什么区别?

2. ES6

2.1. let、const、var的区别?

2.2. const对象的属性可以修改吗?

2.3. 如果new一个箭头函数的会怎么样?

2.4. 箭头函数与普通函数的区别

2.5. 箭头函数的this指向哪⾥?

2.6. 扩展运算符的作用及使用场景

2.7. Proxy 可以实现什么功能?

2.8. 对对象与数组的解构的理解

2.9. 如何提取高度嵌套的对象里的指定属性?

2.10. 对 rest 参数的理解

2.11. ES6中模板语法与字符串处理

3. JavaScript基础

3.1. new操作符的实现原理

3.2. map和Object的区别

3.3. map和weakMap的区别

3.4. JavaScript有哪些内置对象

3.5. 常用的正则表达式有哪些?

3.6. 对JSON的理解

3.7. JavaScript脚本延迟加载的方式有哪些?

3.8. JavaScript 类数组对象的定义?

3.9. 数组有哪些原生方法?

3.10. Unicode、UTF-8、UTF-16、UTF-32的区别?

3.11. 常见的位运算符有哪些?其计算规则是什么?

3.12. 为什么函数的 arguments 参数是类数组而不是数组?如何遍历类数组?

3.13. 什么是 DOM 和 BOM?

3.14. 对类数组对象的理解,如何转化为数组?

3.15. escape、encodeURI、encodeURIComponent 的区别

3.16. 对AJAX的理解,实现一个AJAX请求

3.17. JavaScript为什么要进行变量提升,它导致了什么问题?

3.18. 什么是尾调用,使用尾调用有什么好处?

3.19. ES6模块与CommonJS模块有什么异同?

3.20. 常见的DOM操作有哪些?

3.21. use strict是什么意思 ? 使用它区别是什么?

3.22. 如何判断一个对象是否属于某个类?

3.23. 强类型语言和弱类型语言的区别

3.24. 解释性语言和编译型语言的区别

3.25. for…in和for…of的区别

3.26. 如何使用for…of遍历对象

3.27. ajax、axios、fetch的区别

3.28. 数组的遍历方法有哪些?

3.29. forEach和map方法有什么区别?

4. 原型与原型链

4.1. 对原型、原型链的理解

4.2. 原型修改、重写

4.3. 原型链指向

4.4. 原型链的终点是什么?如何打印出原型链的终点?

4.5. 如何获得对象非原型链上的属性?

5. 执行上下文/作用域链/闭包

5.1. 对闭包的理解

5.2. 对作用域、作用域链的理解

5.3. 对执行上下文的理解

6. this/call/apply/bind

6.1. 对this对象的理解

6.2. call() 和 apply() 的区别?

6.3. 实现call、apply 及 bind 函数

7. 异步编程

7.1. 异步编程的实现方式?

7.2. setTimeout、Promise、Async/Await 的区别

7.3. 对Promise的理解

7.4. Promise的基本用法

7.5. Promise解决了什么问题

7.6. Promise.all和Promise.race的区别的使用场景

7.7. 对async/await 的理解

7.8. await 到底在等啥?

7.9. async/await的优势

7.10. async/await对比Promise的优势

7.11. async/await 如何捕获异常

7.12. 并发与并行的区别?

7.13. 什么是回调函数?回调函数有什么缺点?如何解决回调地狱问题?

7.14. setTimeout、setInterval、requestAnimationFrame 各有什么特点?

8. 面向对象

8.1. 对象创建的方式有哪些?

8.2. 对象继承的方式有哪些?

9. 垃圾回收与内存泄漏

9.1. 浏览器的垃圾回收机制

9.2. 哪些情况会导致内存泄漏

你可能感兴趣的:(Interview,前端开发,面试,JavaScript)