JS面试题

本文列举了26个JavaScript面试中常问的问题,包括数据类型、变量声明、ES6特性、数据类型判断、闭包、事件代理、事件循环、垃圾回收机制、原型链、new操作符、面向对象、Promise、函数方法、数组操作、防抖节流、ES6数组方法、延迟加载、null和undefined的区别、数组方法、继承方式、深浅拷贝、本地存储与cookie的差异以及箭头函数与普通函数的区别。这些问题涵盖了JS基础到进阶的多个方面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 目录

1、说一说常见的数据类型?

2、var、const和let区别?

4、如何判断JS数据类型?

5、讲一下闭包? 

6、什么是事件代理?

7、事件循环?

8、什么是宏任务和微任务?

9、JS运行机制,代码执行机制?

10、数组常见的方法:

11、说一说js的垃圾回收机制

12、原型链?

13、JS中new操作符做了哪些事情?

14、如何理解JS中的面向对象的?

15、说一说promise?

16、你知道call、bind、apply的区别吗?

17、数组去重?

18、说一说防抖和节流?

19、ES6新增数组方法? 

20、延迟加载JS有哪些方式?

21、null和undefined的区别?

22、slice是干嘛的、splice是否会改变原数组?

23、JS的继承方式有哪些?

24、JS的深浅拷贝?

25、localStorage、sessionStorage、cookie的区别?

26、箭头函数和普通函数的区别?



1、说一说常见的数据类型?

基本数据类型:String、Number、Boolean、Undefined、Null、Symbol、BigInt

引用数据类型:object(array、function、date、math、Reg)

2、var、const和let区别?

var声明的变量为全局作用域、而let声明的变量为块级作用域、const声明的常量为块级作用域。var声明的变量存在变量提升,而const和let不存在变量的提升。var可以重复声明同一个变量、let和const不能声明同一个变量,const声明的值不能修改,但是如果const声明的是一个对象,对象里面的属性和值可以修改.

3、ES6新增的特性

let、const,箭头函数、模板字符串、解构赋值、扩展运算符、set、map、promise对象。

4、如何判断JS数据类型?

typeOf:返回判断数据的类型。对于简单数据类型,除了null返回object,其他都可以正确判断。对于引用数据类型,除了function外都会返回object。

instanceof:判断对象的原型链__proto__上是否存在构造函数的原型prototype,只能判断引用数据类型,不能判断基本数据类型,常用来判断a是否为b的实例。

object.prototype.toString.call():返回类型为[object 数据类型]

5、讲一下闭包? 

函数嵌套函数,内部函数就是闭包。内部函数可以访问外部函数中的变量,内部函数没有执行完毕,外部函数中的变量不会被销毁。作用:封装一段代码,避免全局变量污染问题。

6、什么是事件代理?

事件代理也叫事件委托。就是把原本绑在子元素上的点击事件绑定在父元素身上,通过事件冒泡原理父元素可以监听到子元素上的点击事件,触发相应的操作。举例:ul中li标签的事件监听,把原本绑定在li上边的监听事件绑定在ul上,这样的好处是可以实现动态元素的绑定。

7、事件循环?

由于js为单线程,当遇到同步任务和异步任务时,一般把同步任务放在运行栈中,当遇到异步任务的时候会把异步任务放到任务队列中,直到同步任务执行完毕之后再执行异步任务,由于一次只能处理一个异步任务,所以处理完一个异步任务后又会在任务队列中查找下一个任务,以次循环往复直到执行完最后一个任务就称为事件循环。

8、什么是宏任务和微任务?

宏任务:计时器、ajax、dom事件

微任务:promise.then、process.nextTick

9、JS运行机制,代码执行机制?

JS为单线程,一个任务执行完毕才能执行下一个任务。执行顺序为同步程序执行完成后,执行异步程序

(1)同步任务(2)微任务(3)宏任务

10、数组常见的方法:

增:push(末尾)、unshift(开头)、concat(连接两个数组)

删:pop(末尾)、shift(开头)splice(第一个参数为开始位置、第二个参数为删除数量)、slice

查:indexOf()返回要查找元素在数组中的位置,没找到返回-1、includes()返回要查找元素在数组中的位置,找到返回true、找不到返回false、find()返回第一个匹配的元素

reverse、sort、join

11、说一说js的垃圾回收机制

垃圾回收机制简称GC,JS中的内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收,如果不再用到的内存没有得到及时释放,会造成内存泄漏。

内存的生命周期是:内存分配、内存使用、内存回收。全局变量一般不会回收,关闭页面回收,一般情况局部变量的值不再使用了就会自动回收。

12、原型链?

有一个构造函数,通过new实例一个对象,我们在构造函数的prototype身上添加一个方法,如果实例对象想要使用这个方法,就可以通过实例对象.__proto__来访问这个方法,如果找不到,就会在这个对象的原型的原型上进行查找,一层层查找,直到原型链的末尾,就形成了一条原型链。

13、JS中new操作符做了哪些事情?

(1)创建了临时对象/空对象(2)这个对象的原型指向构造函数的prototype(3)this指向这个对象(4)执行构造函数(5)返回临时对象。

14、如何理解JS中的面向对象的?

面向对象是一种编程思想,简称oop 

在es5中创建对象的方式:

(1)对象字面量形式:var obj = {}

(2)new Object()构造函数:var Obj = new Object()

(3)构造函数模式

面向对象的三大特征:封装性、继承性、多态性

优势:易于维护、代码可读性高、易扩展

对象遍历:可以用:for...in...

对象转换为字符串:JSON.stringify()、JSON.parse()

设计模式:

单例模式、工厂模式、观察者模式、订阅模式

es6: (1)class类名称

        (2)static静态属性

        (3)constructor构造函数

        (4)super父类构造函数

        (5)extends继承关键

15、说一说promise?

promise是es6新增的技术,它是一种异步编程的新的解决方案,它是一个对象,通过new创建,promise有三种状态:pending(初始)、fulfilled或resolve(成功)、rejected(失败),它的状态改变有两种可能:从pending到fulfilled,从pending到rejected,这两种情况只要发生,状态就不会再变了。支持链式调用,可以解决回调地狱问题。api:then、catch、race、all、try。

16、你知道call、bind、apply的区别吗?

区别:(1)三者都可以改变函数的this指向。

        (2)apply和call可以会立即执行,而bind会返回一个函数,后续需要的时候再调用执行

        (3)call和bind传递参数一次列出的,apply传递的参数是数组。

17、数组去重?

(1)indexOf:循环去重

(2)Set去重:Array.from(new Set(array))或者Array.from(...new Set(array))

let arr1 = [1, 2, 3, 1, 2, 5]
        function unique(arr) {
            return [...new Set(arr)]
        }
        console.log(unique(arr1));

(3)includes去重

18、说一说防抖和节流?

防抖:当用户多次触发回调函数时,只触发最后一次操作的,其余的全部忽略掉。
函数节流:是确保函数特定的时间内至多执行一次。

19、ES6新增数组方法? 

 (1)forEach函数:数组.forEach(function(属性值){相应操作})

let arr = ['red', 'pink', 'blue', 'black']
        let newArr = arr.forEach((item) => {
            console.log(item); // red pink blue black
        })

(2)map方法:一定要有返回值,否则就会返回undefined,返回值是一个数组。

应用场景:返回一个要利用原数组经过运算后的数组,或者在一个对象数组中拿到某个属性,并返回一个新数组的情况。

let arr1 = ['西游记', '红楼梦', '三国演义', '水浒传']
        let arr2 = arr1.map(item => {return item})
        console.log(arr2); // ['西游记', '红楼梦', '三国演义', '水浒传']

 (3)filter可以返回一个新数组,也可以改变原数组。

 let carBand = ['奔驰', '宝马', '丰田', '本田', '五菱宏光']
        let benChi = carBand.filter((product) => {
            return product === '奔驰'
        })
        console.log(benChi);

(4)find()方法:只会找到第一个符合的,找到之后就会返回,就算下面还有符合要求的,也不会再找下去。

let number = [2, 5, 6, 8, 10, 15, 12, 2]
        let even = number.find((item) => {
            return item % 2 === 0
        })
        console.log(even); // 2

(5)some方法:只要有一个满足就行,一真即真

let persons = [
            {name: '张三',age: 15}, 
            {name: '李四',age: 25}, 
            {name: '王五',age: 30}
        ]
        let some = persons.some((person) => {
            return person.age > 20
        })
        console.log(some); // true

(6)every方法:要所有的满足才行,一假即假

let persons = [
            {name: '张三',age: 15}, 
            {name: '李四',age: 25}, 
            {name: '王五',age: 30}
        ]
        let every = persons.every((person) => {
            return person.age < 20
        })
        console.log(every); //false

(7)reduce()方法:reduce(function(sum,number){...},0),要有两个参数,第一个参数一定要初始化

 let numbers = [5, 10, 15]
        let res = numbers.reduce((sum, number) => {
            console.log(sum);
            return sum + number
        }, 0)
        console.log(res); // 30

20、延迟加载JS有哪些方式?

延迟加载:defer、async

例子:

<script defer type = "text/javascript" src='demo.js'>

defer:所有的html执行完,然后依次执行js代码。

async:与html同步执行。

21、null和undefined的区别?

(1)null会被隐式转换为0,空对象指针;undefined转为数值为NaN

(2)null是个对象、undefined是个undefined类型(typeof判断)

22、slice是干嘛的、splice是否会改变原数组?

(1)slice是来截取的

slice(2)、slice(1,3)、slice(-3)

返回一个新数组

(2)splice:插入、删除、替换

返回删除的元素、该方法会改变原数组

23、JS的继承方式有哪些?

方式一:ES6继承

 class Parent {
            constructor() {
                this.age = 20
            }
        }
        class Children extends Parent {
            constructor() {
                super();
                this.name = '小明'
            }
        }
        let p1 = new Children()
        console.log(p1, p1.name, p1.age);

方式二:原型链继承

function Parent() {
            this.age = 25
        }

        function Children() {
            this.name = '小明'
        }
        Children.prototype = new Parent()
        let p2 = new Children()
        console.log(p2, p2.name, p2.age);

方式三:借用构造函数继承

 function Parent() {
            this.age = 28
        }

        function Children() {
            Parent.call(this)
            this.name = '小明'
        }
        let p3 = new Children()
        console.log(p3, p3.name, p3.age);

方式四:组合式继承

function Parent() {
            this.age = 30
        }

        function Children() {
            Parent.call(this)
            this.name = '小明'
        }
        Children.prototype = new Parent()
        let p4 = new Children()
        console.log(p4, p4.name, p4.age);

24、JS的深浅拷贝?

浅拷贝:只复制引用,没复制真正的值。

let obj1 = {a: 10,b: 20,c: 30}
let obj2 = obj1
obj1.a = 30
console.log(obj1,obj2)
let obj1 = {a: 10,b: 20,c: 30}
let obj3 = Object.assign(obj1)
obj3.b = 100
console.log(obj1, obj3);

深拷贝:是复制真正的值(不可引用)

let obj4 = {a: 1,b: 2}
let obj5 = JSON.parse(JSON.stringify(obj4))
obj5.a = 10
console.log(obj4, obj5);

递归形式:

function copyObj(obj) {
  if (Array.isArray(obj)) {
     var newObj = []
  } else {
     var newObj = {}
  }
    for (var key in obj) {
      if (typeof obj[key] == 'object') {
        newObj[key] = copyObj(obj[key]);
      } else {
        newObj[key] = obj[key]
      }
    }
          return newObj;
 }
   

25、localStorage、sessionStorage、cookie的区别?

(1)数据存储有效期:

sessionStorage:浏览器关闭前有效

localStorage :永久存储,除非手动删除

cookie:只在设置过期时间内有效

(2)cookie可以设置过期时间,sessionStorage、localStorage不可以设置过期时间

(3)存储大小的限制

cookie大小不超过4k,sessionStorage、localStorage不超过5M

26、箭头函数和普通函数的区别?

(1)this指向

箭头函数的this只在箭头函数定义时就决定,而且不能修改this指向

箭头函数this指向定义时,外层第一个普通函数的this

(2)箭头函数不能new(不能当做构造函数)

(3)箭头函数没有arguments

(4)箭头函数没有prototype

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值