前端高频面试题—JavaScript篇(四)

💻 前端高频面试题—JavaScript篇(四)🏠专栏:前端面试题
👀个人主页:繁星学编程🍁
🧑个人简介:一个不断提高自我的平凡人🚀
🔊分享方向:目前主攻前端,其他知识也会阶段性分享🍀
👊格言:☀️没有走不通的路,只有不敢走的人!☀️
👉让我们一起进步,一起成为更好的自己!!!🎁

前端高频面试题—JavaScript篇(四)

本文主要讲述的前端高频面试题知识有:

  1. 原型 / 构造函数
  2. 原型链
  3. 说一下Promise
  4. 事件轮询机制
  5. 设计模式
  6. 继承

一. 原型 / 构造函数

(1) 原型

什么是原型?

将公共的方法提取出来,都写在原型上(只用书写和创建一次)

原型概念

每一个函数都有一个特殊的属性叫做原型(prototype)

每一个对象:天生自带一个属性 __proto__(指向所属构造函数的原型)

原型对象有一个自有属性constructor,这个属性指向该函数

问答?

  1. 原型是什么 ?

    一个对象,我们也称为 prototype 为原型对象。

    JavaScript 常被描述为一种基于原型的语言——每个对象拥有一个原型对象

  2. 原型的作用是什么 ?

    共享方法。

  3. 为什么要使用原型对象

    因为构造函数方法虽然很好用,但是存在浪费内存的问题。每一次调用构造函数中的方法都会重新开辟一块新的内存存储(浪费了空间),而原型对象(prototype)可以对象共享可以节省内存。

(2) 构造函数

1. 概念

构造函数其实就是一个函数,只不过使用的时候需要和new 关键字连用,首字母大写。

和普通函数一样, 只不过调用的时候要和 new 调用 ,不然就是一个普通函数调用

const fn = function(age) {
    let a = 1; // 块作用域,外面无法获取,内部使用
    var b = 2; // 局部变量,外面无法获取,内部使用
    this.age = age; // 属性,实例对象可以自由获取,this->实例对象 
};

let f1 = new fn(18);
let f2 = new fn; // 这种写法也支持,弊端是无法传递参数

注意: 不写 new 的时候就是普通函数调用,没有创造对象的能力,但如果只是首字母不大写,只要和 new 连用,就有创造对象的能力。

2. 构造函数特点总结

  1. 首字母大写(推荐)

    方便区分

  2. 构造函数里面不要书写return

    构造函数里没有显式调用return,默认返回的是this对象,也就是新创建的实例对象。

    当构造函数里调用return时,分两种情况:

    ​ 1.return的是五种简单数据类型:String,Number,Boolean,Null,Undefined。

    ​ 这种情况下,忽视return值,依然返回this对象。

    ​ 2.return的是Object

    ​ 这种情况下,不再返回this对象,而是返回return语句的返回值。

  3. 构造函数的调用必须和new连用

    只有和new连用,才有构造函数的能力,不和new连用,就是一个普通函数

  4. 构造函数的this

    构造函数的this指向:本次调用被自动创建的对象

    • 自动创建出来的对象叫做 实例对象
    • 这个创建对象的过程叫做 实例化 的过程
  5. 箭头函数没有this , 构造函数不能使用箭头函数书写

二. 讲讲原型链?

面试官主要询问点

__proto__和prototype之间的关系,以及对于属性的向上查找这些一定要清楚的

原型链:使用__proto__串联起来的链状结构

对象的访问机制

当访问一个对象成员的时候

  • 首先在该对象自己身上查找,如果有直接使用,停止查找
  • 如果没有,会自动去到__proto__查找,如果有直接使用,停止查找
  • 如果仍然没有,继续去到__proto__在上一级查找
  • 如果没有找到,返回undefined, (找到了原型链的顶级 null)

官方:每个实例对象(object)都有一个私有属性(称之为 proto)指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(proto),层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。

/*
  七个指向问题:(p ==> Person的实例对象)
  	寻找思路主要还是要先了解:该对象所属的构造函数是什么?
  		1.p.__pro__                     ==> Person.prototype
  		2.Person.prototype.__proto__    ==> Object.prototype
  		3.Person.__proto__              ==> Function.prototype
  		4.Function.__proto__            ==> Function.prototype
  		5.Object.__proto__              ==> Function.prototype
  		6.Function.prototype.__proto__  ==> Object.prototype
  		7.Object.prototype.__proto__    ==> null

原型链指向图

请添加图片描述

三. 说一下Promise

面试官主要询问的点

  • a. 目的
  • b. 状态
  • c. 改变状态
  • d. 方法
  • e. async await
  1. 目的:解决回调地狱

  2. 状态

    持续:pending

    成功:fulfilled

    失败:rejected

  3. 改变状态

    从持续状态转换到成功

    从持续状态转换到失败

  4. 方法

    Promise 的实例原型方法

    • then(函数):成功状态的时候执行的方法
    • catch(函数):失败状态的时候执行的方法
    • finally(函数) :结束时执行的方法,不管状态是成功还是失败,finally都会执行

    Promise 本身的一些方法:

    1. all

      语法:Promise.all([多个 Promise])

      作用:用于将多个 Promise 实例,包装成一个新的 Promise 实例,接受一个数组作为参数,只有数组里面的每个状态都变成resolve,则新的 Promise 实例状态才会变成resolve。

    2. race

      语法:Promise.race([多个promise])

      作用:将多个 Promise 实例,包装成一个新的 Promise 实例,接受一个数组作为参数,只要其中有一个实例率先改变状态,则整个的状态就跟着改变。

    3. allSettled (ES2020)

      语法:Promise.allSettle([多个promise])

      作用:方法接受一个数组作为参数,数组的每个成员都是一个 Promise 对象,并返回一个新的 Promise 对象。只有等到参数数组的所有 Promise 对象都发生状态变更(不管是fulfilled还是rejected),返回的 Promise 对象才会发生状态变更。

      简单理解就是:不管是成功还是失败,都会触发,并会把结果用数组的形式返回,数组里面放着每一个promise的结果

    4. Promise的方法(主要是开发人员调试用的)

    ​ resolve()强行把promise的状态改为成功

    ​ reject()强行把Promise的状态改为失败

四. 事件轮询机制

事件轮询 (客户端)

开始轮询时间:从开始执行代码的时候就开始执行轮询

规则

  1. 从第一个宏任务开始(一般是整个JavaScript代码段)
  2. 每执行完一个宏任务,清空一次微任务队列里面的所有内容
  3. 然后再执行一个宏任务
  4. 往复执行以上操作,直到所有队列任务都清空结束

关键词

  • 单线程:JS是一个单线程的代码执行机制,如果逐行执行代码, 会阻塞代码执行
  • 调用栈:用来执行代码的空间 (栈: 后进先出)
  • 队列:存放异步任务 (队列: 先进先出)
  • 宏任务队列:JS整块代码(script)、setTimeout、setInterval…
  • 微任务队列:Promise.then…

请添加图片描述

五. 设计模式

常见的设计模式:

  1. 单例模式

    单例模式的定义是:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

    单例模式核心:实例化一个类的时候

    先判断,之前有没有实例化过

    • 如果有,就用之前的
    • 如果没有,就实例化一个新的

    场景:在点击按钮需要出现一个弹窗时,我们只希望无论点击多少次,都出现只出现一个弹窗。

  2. 策略模式

    策略模式的定义是:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。

    策略模式的目的是:将算法的使用与算法的实现分离开来

  3. 发布订阅模式

    发布-订阅模式其实是一种对象间一对多的依赖关系,当一个对象的状态发送改变时,所有依赖于它的对象都将得到状态改变的通知。

    订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel),当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。

    例子:比如我们很喜欢看某个公众号号的文章,但是我们不知道什么时候发布新文章,要不定时的去翻阅;这时候,我们可以关注该公众号,当有文章推送时,会有消息及时通知我们文章更新了。

    上面一个看似简单的操作,其实是一个典型的发布订阅模式,公众号属于发布者,用户属于订阅者;用户将订阅公众号的事件注册到调度中心,公众号作为发布者,当有新文章发布时,公众号发布该事件到调度中心,调度中心会及时发消息告知用户。

六. 继承

继承:一个构造函数中的实例使用另一个构造函数上的属性和方法

(1). 为什么要学习继承?

写的构造函数, 定义了⼀个类型 (⼈类), 万⼀项⽬⾮常⼤, ⼜有了细化的多个类型 (⽼师, ⼯⼈, 学⽣)
学习继承, 可以让多个构造函数之间建⽴关联, 便于管理和复⽤

(2). 什么是继承?

继承: 从别⼈那⾥, 继承东⻄过来 (财产, 房产)
代码层⾯的继承: 继承⼀些属性构造的过程和⽅法

(3). 原型继承

1. 原型继承的概念

  • 利用自定义原型的方法来实现继承关系
  • 核心:子类的原型指向父类的实例
Son.prototype = new Father()

2. 原型继承的原理

子类的原型(Son.prototype)指向了父类的实例(new Father()也就是f)

子类实例化的对象想要访问一个属性时:

  • 首先在自己身上寻找,
  • 如果没有,沿着 __proto__ 寻找,
  • 子类的实例化对象的s.__proto__指向的是所属的构造函数的原型 Son.prototype == f

3. 原型继承的优缺点

优点:可以实现继承父类的属性和方法

缺点:

  1. 子类的原型被占用,之后往子类的原型上加属性和方法无效
  2. 继承下来的属性不在子类身上,在原型身上

(4). 借用继承

1. 概念

借用继承又叫:借用构造函数继承、call继承

核心:把父类构造函数当做普通函数用,并利用call()、apply()、bind()()修改this的指向

2. 优缺点

优点:

  1. 可以把属性继承在自己身上
  2. 有自己的原型

缺点:只能继承父类的属性,不能继承原型的方法

(5). 组合继承

1. 概念

把原型继承和借用继承组合在一起

(2) 优缺点

优点:

  1. 可以继承属性和方法
  2. 继承的属性在自己身上

缺点:原型上存在一套属性

(6). 拷贝继承

拷贝继承:把父类身上的所有内容复制一份放在子类的原型上

实现:利用 for…in 循环遍历对象

in 关键字的作用

判断字符串是不是对象上的一个属性
返回值:true/false
特点:不只是对象本身,原型上的也能访问到

(7). 类继承

class 子类 extends 父类{
    constructor(){
        // 必须先写一个super() 相当于借用继承中把父类的方法用call在子类中执行一次
        super()
        /*
        	super 关键字用于访问和调用一个对象的父对象上的函数。
        	在构造函数中使用时,super关键字将单独出现,并且必须在使用 this 关键字之前使用。super 关键字也可以用来调用父对象上的函数。
         */
    } 
}

结束语

希望对您有一点点帮助,如有错误欢迎小伙伴指正。
👍点赞:您的赞赏是我前进的动力!
⭐收藏:您的支持我是创作的源泉!
✍评论:您的建议是我改进的良药!
一起加油!!!💪💪💪

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

繁星学编程

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

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

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

打赏作者

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

抵扣说明:

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

余额充值