js高频重点面试

本文详细介绍了JavaScript中的重要概念,包括闭包及其优缺点,防抖与节流的应用,柯里化的原理,以及作用域、作用域链、事件轮询、Ajax的工作原理。同时,讨论了原型、原型链、this指向问题,以及call、apply、bind的区别。文章还涵盖了深拷贝、浅拷贝和递归在深拷贝中的应用。

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

闭包是什么

一句话:闭包是指有权访问另一个函数作用域中变量的函数

使一个函数能访问另一个函数作用域中的变量

闭包优缺点

  • 使用闭包的优点是可以避免全局变 量污染,延长变量生命周期。

  • 缺点是由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在低版本IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除

防抖和节流,以及应用场景

简述:

(1)防抖:就是将一段时间内连续的多次只会执行最后一次触发。

(2)节流:减少一段时间内触发的频率

场景:

防抖:earch搜索联想,用户在不断输入值时或者登录时点击按钮

节流:鼠标拖拽

柯里化

柯里化是一个函数,它一次接受一个参数,并返回一个新函数,该函数期待下一个参数,利用闭包的原理。它是一种函数转换,将 f(a,b,c) 转换为可以被以 f(a)(b)(c) 的形式进行调用。

优点:

  • 可以把函数式编程变得简洁,没有冗余。

  • 可以将函数作为返回值输出,提前返回。

纯函数

1.返回值只和函数参数有关,与外部无关。无论外部发生什么样的变化,函数的返回值都不会改变

2.函数内部创建的变量。进行修改则不会产生副作用

总结:简单的说就是一个函数的返回结果只依赖其参数,并且执行过程中没有副作用。

作用域

所谓作用域就是变量可作用的范围

作用域链

在函数嵌套下,由内向外的链式规则就叫作用域链

事件轮询(Event Loop)

  • JS是单线程的,即同一时间只能执行一个任务

  • 在JS中,任务分为同步任务和异步任务

    1. 同步任务:在主线程上执行的,形成一个执行栈,前一个任务执行完后执行后一个任务

      • 比如for循环,事件绑定,Dom...

    2. 异步任务:通过回调函数实现在做任务的同时还能做其他任务

      • 比如定时器的回调,ajax的回调,事件函数

  • 异步任务又分为宏任务和微任务

    • 宏任务:setTimeout,setInterval,ajax,dom事件监听...

    • 微任务:promise,.then,async/await...

      执行过程

      • 优先执行同步任务,遇到异步任务推入任务队列中,等同步任务执行完再执行任务队列中的异步任务,异步任务中又分宏任务和微任务,先执行微任务,再执行宏任务

Ajax原理是什么?实现步骤?

通过 XmlHttpRequest 对象来向服务器发异步请求,从服务器获得数据,然后⽤ JavaScript 来操作 DOM ⽽更新⻚⾯。

步骤:

  1. 创建XMLHttpRequest对象,即创建一个异步调用对象.

  2. 创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.

  3. 设置响应HTTP请求状态变化的函数.

  4. 发送HTTP请求.

  5. 获取异步调用返回的数据.

什么是原型?

原型是function对象的一个属性,定义了构造函数创造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。

什么是prototype?

显示原型,是函数(不包含箭头函数)本身存在的一个属性,他指向的是一个对象,即为原型对象。

什么是 __ proto __ ?

可以称为隐式原型,或者叫连接点。是对象的一个属性,它里面存储的是该构造函数的原型对象,即prototype.

什么是构造函数?

构造函数其实是一种特殊的函数,主要用来初始化对象,也就是为对象成员变量赋初始值,它总与new关键字一起使用

什么是原型链?

当我们访问一个实例(例如person)的属性或方法时,会先在当前实例上查找,若查找不到,会到原型上查找,若原型上查找不到,就到原型的原型上查找,若还是查找不到就指向null

原型的优点

如果方法不放在原型上继承的缺点:

  • 如果方法不放在原型上面的话,构造函数创建对象的时候 ,当构造函数的方法很多的时候,其结构很冗余复杂。

  • 每次实例一个对象,都需要开辟一个空间,造成内存严重浪费

  • 每一个对象的属性和方法都是独立的,不会互相影响,这就无法做到数据共享

原型思想的继承的优点:

  • 可以让构造函数结构变得简单

  • 可以节省内存的空间

  • 每一个实例可以共享原型上的方法和属性,达成数据共享

原型思想的继承的缺点:

***因为数据存在共享,所以可以被修改或者覆盖

hasOwnProperty() 和 in()操作符的区别

1.hasOwnProperty 只能检测对象实例属性,无法检测原型中的属性

2.in 只要能访问到的属性都可以检测到

this指向问题

第一种:

默认绑定 指向window

1: 直接在全局中打印this 直接指向 全局环境

2: 独立调用函数 指向window

第二种

隐式绑定 : 谁调用 指向谁

第三种 显示绑定

1:call

2:apply

3:bind

第四种:new绑定绑定在实例上

第五种:

箭头函数的this

箭头函数的this其实是根据他的上级决定,也就是他的this指向等于他的上级上下文。

优先级

箭头函数 > new > call,apply bind >obj. >默认绑定

call,apply,bind的区别

call: 第一个参数: 要更改的this指向(上下文) 第二个参数 传值的参数 单个形式传递呢

apply: 第一个参数: 要更改的this指向(上下文) 第二个参数 传值的参数 以数组的形式进行打包传递

bind: 有返回值,是一个新的函数。多次绑定的时候,只认第一次绑定的上下文

new都干了些什么事?

1: 在内存中创建一个空对象 {};

2: 将空对象的原型指向构造函数的原型;

3: 将空对象作为构造函数的上下文(即改变this指向);

4: 对有返回值的构造函数做判断。

继承

第一种:盗用构造函数

缺点: 1:无法继承原型上的属性和方法

2:构造函数的代码不简洁

第二种:原型链继承(原型继承)【 子类的原型继承父类的对象】

缺点:由于原型链是所有实例的公共祖先,所以容易引发 当原型更改,实例全部更改的结果。

第三种:组合继承(构造函数继承 + 原型继承)

父类被调用两次,浪费资源

第四种:原型式继承

第五种:寄生式继承

第六种:寄生式组合继承

 1:利用Object.create()创建一个对象,将父类的原型赋值给新对象,并将此对象给子类原型
  2:将子类的构造函数更改回自己。

1:什么是深拷贝

另外创建一个一摸一样的对象,新对象跟原对象不共享内存,修改新对象不会更改原对象

2:什么是浅拷贝

只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共存一块内存

递归的思想:

在深拷贝之前,会判断是否为数组或对象,如果是数组或对象,我会用for循环遍历每一项,赋值给事先准备好的空数组或空对象,如果是一个多维数组或对象 会选择使用递归去复制

深拷贝使用深度递归注意什么?

无论是否为深拷贝使用递归,平时我们使用递归的时候,也需要考虑是否存在时候循环引用的情况 在深拷贝中,我们可以将每一次的递归记录存在weakmat中,每一次递归前先去查找是否存在相同记录,若存在,返回该记录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Pinia-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值