• js常见面试题


    01 - 数据类型

    值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。

    引用数据类型(对象类型):对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)。

    02 - 检测数据类型

    type of

    可以正常检测出:number、boolean、string、object、function、undefined、symbol、bigint

    • 检测基本数据类型,null会检测object,因为null是一个空的引用对象
    • 检测复杂数据类型,除function外,均为object
    instanceof

    instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链

    注意:只能检测复杂数据类型

    toString

    toString() 是 Object 的原型方法,调用该方法,默认返回当前对象的 [[Class]] 。这是一个内部属性,其格式为 [object Xxx] ,其中 Xxx 就是对象的类型

    对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,则需要通过 call / apply 来调用才能返回正确的类型信息。

    Object.prototype.toString.call('') ;  // [object String]
    Object.prototype.toString.call(1) ;   // [object Number]
    
    • 1
    • 2
    constructor
    代表获取由哪个构造函数创建而出,可以检测出字面量方式创建的对象类型,因为字面方式创建,实际由对应类创建而出
    不是字面量的方式只会获取到构造函数
     const dog = new Animal('大黄')
        console.log(dog.constructor === Object) // false
        console.log(dog.constructor === Animal) // true
    
    • 1
    • 2
    • 3
    • 4
    • 5

    isArray可以检测出是否为数组

    03 - 作用域

    通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

    作用域的作用:

    • 提高了程序逻辑的局部性。
    • 增强了程序的可靠性,减少了名字冲突。

    JavaScript(es6前)中的作用域有两种:

    • 全局作用域

      作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件。
      
      • 1
    • 局部作用域(函数作用域)

    • JS没有块级作用域(Es6之前)

    04 - 作用域链

    只要是代码都在一个作用域中,写在函数内部的局部作用域,未写在任何函数内部即在全局作用域中;如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域;根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链

    05 - 原型链和成员的查找机制

    任何对象都有原型对象,也就是prototype属性,任何原型对象也是一个对象,该对象就有__proto__属性,这样一层一层往上找,就形成了一条链,我们称此为原型链;

    当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性。
    如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)。
    如果还没有就查找原型对象的原型(Object的原型对象)。
    依此类推一直找到 Object 为止(null)。
    __proto__对象原型的意义就在于为对象成员查找机制提供一个方向,或者说一条路线。
    
    • 1
    • 2
    • 3
    • 4
    • 5

    06 - 谈谈你对 this 的理解?

    this 是一个在运行时才进行绑定的引用,在不同的情况下它可能会被绑定不同的对象。

    默认绑定 (指向 window 的情况) (函数调用模式 fn() )

    默认情况下,this 会被绑定到全局对象上,比如在浏览器环境中就为window对象,在 node.js 环境下为global对象。

    隐式绑定 (谁调用, this 指向谁) (方法调用模式 obj.fn() )

    如果函数的调用是从对象上发起时,则该函数中的 this 会被自动隐式绑定为对象

    显式绑定 (又叫做硬绑定) (上下文调用模式, 想让 this 指向谁, this 就指向谁)

    硬绑定 => call apply bind

    new 绑定 (构造函数模式)

    另外,在使用 new 创建对象时也会进行 this 绑定

    当使用 new 调用构造函数时,会创建一个新的对象并将该对象绑定到构造函数的 this

    07 - 箭头函数中的 this 指向什么?

    箭头函数不同于传统函数,它其实没有属于⾃⼰的 this

    它所谓的 this 是, 捕获其外层 上下⽂的 this 值作为⾃⼰的 this 值。

    并且由于箭头函数没有属于⾃⼰的 this ,它是不能被 new 调⽤的。

    08 - 如何判断是否是数组?

    方法一:使用 toString 方法

    function isArray(arg) {
      return Object.prototype.toString.call(arg) === '[object Array]'
    }
    
    let arr = [1, 2, 3]
    isArray(arr) // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    方法二:使用 ES6 新增的 Array.isArray 方法

    09 - async/await 是什么?

    ES7 标准中新增的 async 函数,从目前的内部实现来说其实就是 Generator 函数的语法糖。

    它基于 Promise,并与所有现存的基于 Promise 的 API 兼容。

    async 关键字

    1. async 关键字用于声明⼀个异步函数(如 async function asyncTask1() {...}
    2. async 会⾃动将常规函数转换成 Promise,返回值也是⼀个 Promise 对象
    3. async 函数内部可以使⽤ await

    await 关键字

    1. await 用于等待异步的功能执⾏完毕 var result = await someAsyncCall()
    2. await 放置在 Promise 调⽤之前,会强制 async 函数中其他代码等待,直到 Promise 完成并返回结果
    3. await 只能与 Promise ⼀起使⽤
    4. await 只能在 async 函数内部使⽤

    10、Promise 的理解

    Promise 是一种为了避免回调地狱的异步解决方案

    Promise 是一种状态: pending(进行中)、resolve(已成功)和rejected(已失败) 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态

    Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆,只能由 pending变成resolve或者由pending变成rejected

    Promise 是一个构造函数

    Promise 构造函数原型上的方法,可以通过创建一个 Promise 实例进行调用

    • Promise.prototype.then()
    • Promise.prototype.catch()
    • Promise.prototype.finally()

    Promise 构造函数原型上的方法,可以通过创建一个 Promise 实例进行调用

    1-1、静态方法-all

    Promise.all()参数可以传递一个数组,数组中记录所有的 promise 异步处理

    返回值是一个 Promise 的实例对象 then 方法可以获取到所有的 promise 异步处理的结果,一旦有某一个调用执行了 reject,则终止进入 catch

    1-2、静态方法-allSettled

    Promise.all 和 allSettled 基本一样,区别是,then 始终可以获取到异步的状态,哪怕其中有一个失败

    1-3、静态方法-race

    Promise.race 使用和 all 一样,但是只返回第一个结果,不管成功或失败

    1-3、静态方法-any

    Promise.any 返回第一个成功的结果

    11、箭头函数和普通函数的区别

    ​ 箭头函数与普通函数的区别在于:

    1、箭头函数没有this,所以需要通过查找作用域链来确定this的值,这就意味着如果箭头函数被非箭头函数包含,this绑定的就是最近一层非箭头函数的this,

    2、箭头函数没有自己的arguments对象,但是可以访问外围函数的arguments对象

    3、不能通过new关键字调用,同样也没有new.target值和原型

    ​ 1、语法更加简洁、清晰
    ​ 2、箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承 this。
    ​ 3、箭头函数继承而来的this指向永远不变
    ​ 4、.call()/.apply()/.bind()无法改变箭头函数中this的指向
    ​ 5、箭头函数不能作为构造函数使用
    ​ 6、箭头函数没有自己的arguments,可以在箭头函数中使用rest参数代替 arguments对象,来访问箭头函数的参数列表
    ​ 7、箭头函数没有原型prototype
    ​ 8、箭头函数不能用作Generator函数,不能使用yeild关键字
    ​ 9、箭头函数不具有super,不具有new.target

  • 相关阅读:
    算法训练营64-图论-深度优先优先搜索(dfs)-广度优先搜索(bfs)
    质量小议13 -- 侥幸
    [100天算法】-定长子串中元音的最大数目(day 67)
    linux时间调整
    力扣刷题记录3.1-----977. 有序数组的平方
    【C数据存储详解】(2)——深度剖析 浮点型数据 在内存中的存取
    Vue常见的实现tab切换的两种方法
    图片识别文字其实很简单,快来看看这几招
    MogaFX—哈萨克斯坦坚戈汇率10月走强
    【高等数学】五、微分方程
  • 原文地址:https://blog.csdn.net/weixin_46862327/article/details/126819035