2024年Javascript最常见的面试题以及答案,搞懂这些直接来阿里入职

  • instanceof; instanceof 是用来判断 A 是否为 B 的实例;(一般判断引用数据类型)

  • Object.prototype.toString.call()(可判断所有的数据类型,最准确最常用的方式)

typeof 和 instanceof 的区别?

=======================================================================================

typeof:

  • 用来判断基本数据类型,但是typeof null返回的是Object,这只是JavaScript 存在的一个悠久 Bug,不代表null就是引用数据类型,并且null本身也不是对象

  • 引用类型数据,用typeof来判断的话,除了function会被识别出来之外,其余的都输出object

instanceof:

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

  • 主要检测引用数据类型,检测基本类型都返回false;

区别:

  • typeof会返回一个变量的基本类型,instanceof返回的是一个布尔值

  • instanceof 可以准确地判断复杂引用数据类型,但是不能正确判断基础数据类型

  • 而typeof 也存在弊端,它虽然可以判断基础数据类型(null 除外),但是引用数据类型中,除了function 类型以外,其他的也无法判断

  • 如果需要通用检测数据类型,可以采用Object.prototype.toString,调用该方法,统一返回格式“[object Xxx]”的字符串

对栈和堆内存有了解吗,二者的区别?

================================================================================

栈内存:

  • 栈就是我们之前反复提及的调用栈,是用来存储执行上下文的。

  • 栈空间都不会设置太大,栈主要用于来保存基本值和引用类型值的地址

  • 自动分配的相对固定大小的内存空间,其数据读取快,写入速度快,但存储内容少,变量一旦不使用就由系统自动清理释放;

堆内存:

  • 用来保存一组无序且唯一的引用类型值,可以使用栈中的键名来取得

  • 堆的读取和写入速度慢,但存储的内容多,一般对象会存储在堆中,存储的数据对于大小在这方面都是未知的

  • 堆是动态分配的内存,大小不定也不会自动释放。

二者区别:

  • 空间分配区别:栈由操作系统(编译器)自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。堆(操作系统) 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表。

  • 缓存方式区别:栈使用的是一级缓存, 它们通常都是被调用时处于存储空间中,调用完毕立即释放。堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。

  • 数据结构区别:堆可以被看成是一棵树,如:堆排序。栈是一种先进后出的数据结构。

  • 存储类型区别:栈一般来保存基本值和引用类型值的地址;堆用来保存一组无序且唯一的引用类型对象

点击浏览器工作原理和实践——栈空间和堆空间查看详解

深拷贝和浅拷贝的区别?

==========================================================================

浅拷贝:

创建一个新的对象,不会指向同一个地址,这个对象有着原始对象属性值的精确拷贝。就是对象的浅拷贝只会对“主”对象进行拷贝,拷贝的是对象属性的基本类型的值,如果属性是引用类型,拷贝的就是内存地址,拷贝的不深,所以称为浅拷贝;

  • 修改浅拷贝对象第一层的非对象引用类属性,都不会影响原对象

  • 由于浅拷贝不会拷贝对象里面的对象,“里面的对象”会和原对象共享内存,所以修改浅拷贝对象的子属性对象里面的属性,原对象也会受到影响

深拷贝:

深拷贝不仅将元对象的各个属性逐个复制,还将原对象各个属性所包含的对象属性也一次采用深复制的方法递归复制到新对象上,所以修改拷贝后的对象不会影响原对象;

  • 深拷贝是逐层对对象的各个属性进行拷贝,修改拷贝对象任意属性,都不会影响原对象

区别:

| | 和原数据是否指向同一个对象 | 第一层数据为基本数据类型 | 原数据中包含的子对象 |

| — | — | — | — |

| 浅拷贝 | 否 | 不会使原数据一起改变 | 会使原数据一起改变 |

| 深拷贝 | 否 | 不会使原数据一起改变 | 不会使原数据一起改变 |

点击对Javscript中浅拷贝和深拷贝的探索和详解查看详解

项目中实现深浅拷贝常用的方法有哪些?

=================================================================================

实现浅拷贝的方法:

  • 简单赋值

  • 利用 for…in循环实现浅拷贝

  • 利用Object.assign()方法

实现深拷贝的方法:

  • 使用递归的方式实现深拷贝

  • 通过 JSON 对象实现深拷贝

  • slice()、concat()对数组进行深拷贝

点击对Javscript中浅拷贝和深拷贝的探索和详解查看详解

赋值、浅拷贝和深拷贝的区别?

=============================================================================

| | 和原数据是否指向同一个对象 | 第一层数据为基本数据类型 | 原数据中包含的子对象 |

| — | — | — | — |

| 赋值 | 是 | 会使原数据一起改变 | 会使原数据一起改变 |

| 浅拷贝 | 否 | 不会使原数据一起改变 | 会使原数据一起改变 |

| 深拷贝 | 否 | 不会使原数据一起改变 | 不会使原数据一起改变 |

三者的内存图:

赋值

在这里插入图片描述

浅拷贝

在这里插入图片描述

深拷贝

在这里插入图片描述

点击对Javscript中浅拷贝和深拷贝的探索和详解查看详解

new创建一个对象的时候做了些什么?

=================================================================================

  1. 首先创建了一个空对象 obj

  2. 将对象与构建函数通过原型链连接起来

  3. 将构建函数中的this绑定到新建的对象obj上

  4. 根据构建函数返回类型作判断,如果是原始值则被忽略,如果是返回对象,需要正常处理

Javascript中的原型和原型链有了解吗?

======================================================================================

原型:

  • 在 JavaScript 中,每当定义一个对象时候,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype 属性,这个属性指向函数的原型对象。

  • 原型对象都会自动获得一个constructor属性,这个属性是一个指向prototype属性所在函数的指针;

  • 当调用构造函数创建一个新实例后,高实例对象内部将包含一个指针(内部属性_proto_),指向构造函数的原型对象;

  • 原型对象的用途是包含可以由特定类型的所有实例共享的属性和方法。

原型链:

  • 原型链是就是实例对象在查找属性时,如果查找不到,就会沿着__proto__去与对象关联的原型上查找,有则返回,如果找不到,就去找原型的原型,直至查到最顶层Object函数的原型,其原型对象的_proto__已经没有可以指向的上层原型,因此其值为null,返回undefind;

  • 原型链是实现继承的主要方法,其基本思想就是利用原型让一个引用类型继承另一个引用类型的属性和方法;

点击对Javascript中原型和原型链的探索和详解查看详解

说说Javascript中的继承,如何实现继承?

=======================================================================================

继承是什么:

继承(inheritance)是面向对象软件技术当中的一个概念;如果一个类别B“继承自”另一个类别A,就把这个B称为“A的子类”,而把A称为“B的父类别”也可以称“A是B的超类”;

  • 继承可以使得子类具有父类别的各种属性和方法,而不需要再次编写相同的代码

  • 在子类别继承父类别的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类别的原有属性和方法,使其获得与父类别不同的功能

实现继承的方法:

  • 原型链继承

  • 构造函数继承(借助 call)

  • 组合继承

  • 原型式继承

  • 寄生式继承

  • 寄生组合式继承

点击Javascript中的继承和实现方法查看详解

Javascript中的执行上下文和执行栈是什么?

========================================================================================

执行上下文:

执行上下文是对Javascript代码执行环境的一种抽象概念,只要有Javascript代码运行,那么它就一定是运行在执行上下文中;

执行上下文的类型分为三种:

  • 全局执行上下文:只有一个,浏览器中的全局对象就是 window对象,this 指向这个全局对象

  • 函数执行上下文:存在无数个,只有在函数被调用的时候才会被创建,每次调用函数都会创建一个新的执行上下文

  • Eval 函数执行上下文:指的是运行在 eval 函数中的代码,很少用而且不建议使用

执行栈:

执行栈,也叫调用栈,具有 LIFO(后进先出)结构,用于存储在代码执行期间创建的所有执行上下文;

当Javascript引擎开始执行你第一行脚本代码的时候,它就会创建一个全局执行上下文然后将它压到执行栈中

每当引擎碰到一个函数的时候,它就会创建一个函数执行上下文,然后将这个执行上下文压到执行栈中

引擎会执行位于执行栈栈顶的执行上下文(一般是函数执行上下文),当该函数执行结束后,对应的执行上下文就会被弹出,然后控制流程到达执行栈的下一个执行上下文

点击JavaScript的执行机制——调用栈查看详解

说说你对Javascript作用域的理解?

====================================================================================

作用域是指在程序中定义变量的区域,该位置决定了变量的生命周期。通俗地理解,作用域就是变量与函数的可访问范围,即作用域控制着变量和函数的可见性和生命周期。

在 ES6 之前,ES 的作用域只有两种:全局作用域和函数作用域。

  • 全局作用域中的对象在代码中的任何地方都能访问,其生命周期伴随着页面的生命周期。

  • 函数作用域就是在函数内部定义的变量或者函数,并且定义的变量或者函数只能在函数内部被访问。函数执行结束之后,函数内部定义的变量会被销毁。

ES6 出现了块级作用域,块级作用域就是使用一对大括号包裹的一段代码,比如函数、判断语句、循环语句,甚至单独的一个{}都可以被看作是一个块级作用域。

说说你对闭包的理解以及使用场景?

===============================================================================

在 JavaScript 中,根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包。

如果闭包使用不正确,会很容易造成内存泄漏,所以在使用闭包的时候,你要尽量注意一个原则:如果该闭包会一直使用,那么它可以作为全局变量而存在;但如果使用频率不高,而且占用内存又比较大的话,那就尽量让它成为一个局部变量。

任何闭包的使用场景都离不开这两点:

  • 创建私有变量

  • 延长变量的生命周期

场景:

  • 柯里化函数

点击JavaScript的执行机制——作用域链和闭包查看详解

说说你对Javascript中this对象的理解?

========================================================================================

  1. 函数执行时首先看函数名前面是否有".“,有的话,”."前面是谁,this就是谁;没有的话this就是window

  2. 自执行函数中的this永远是window

  3. 在构造函数模式中,类中(函数体中)出现的this.xxx=xxx中的this是当前类的一个实例

  4. call、apply和bind,可以改变this的指向,为函数的第一个参数

  5. 箭头函数的this看外层的是否有函数,如果有,外层函数的this就是内部箭头函数的this,如果没有,则this是window。

Javascript数组常见的方法有哪些?

====================================================================================

操作方法:

  • 增:push()、unshift()、splice()、concat()

  • 删:pop()、shift()、splice()、slice()

  • 改:splice()

  • 查:indexOf()、includes()、find()

排序方法:

  • 数组本身有两个方法:reverse()、sort()

  • 定义排序函数:冒泡排序、插入排序、递并排序、计数排序

转换方法:

  • join()

迭代方法:

  • some()

  • every()

  • forEach()

  • filter()

  • map()

点击Javscript数组中最常用的方法(建议收藏)查看详解

手写一个数组排序方法?

==========================================================================

冒泡排序:

var arr = [3,4,1,2,21,5,15,6,63];

function BubbleSort(ary){

for(var i = 0; i < ary.length - 1; i++){

for(var j = i + 1; j < ary.length; j++){

var current = ary[i];

if(current > ary[j]){

var tmp = ary[j];

ary[j] = current;

ary[i] = tmp;

}

}

}

return ary;

}

1

BubbleSort(arr); // [1, 2, 3, 4, 5, 6, 15, 21, 63]

点击Javscript数组中最常用的方法(建议收藏)查看详解

Javascript字符串常见的方法有哪些?

=====================================================================================

操作方法:

  • 增:concat()、

  • 删:slice()、substr()、substring()

  • 改:trim()、trimLeft()、trimRight()、repeat()、toLowerCase()、 toUpperCase()

  • 查:chatAt()、indexOf()、startWith()、includes()

转换方法:

  • split

模板匹配方法:

  • match()

  • search()

  • replace()

点击Javascript字符串常见的方法查看详解

谈谈Javascript中类型转变机制?

===================================================================================

常见的类型转换有:

  • 强制转换(显示转换)

  • 自动转换(隐式转换)

点击js的六种数据类型、强制类型转换和隐式类型转换查看详解

== 和 === 的区别和使用场景?

==================================================================================

等于操作符:

等于操作符用两个等于号( == )表示,如果操作数相等,则会返回 true;

等于操作符(==)在比较中会先进行类型转换,再确定操作数是否相等;

  • 两个都为简单类型,字符串和布尔值都会转换成数值,再比较

  • 简单类型与引用类型比较,对象转化成其原始类型的值,再比较

  • 两个都为引用类型,则比较它们是否指向同一个对象

  • null 和 undefined 相等

  • 存在 NaN 则返回 false

全等操作符:

全等操作符由 3 个等于号( === )表示,只有两个操作数在不转换的前提下相等才返回 true。即类型相同,值也需相同

区别:

  • 相等操作符(==)会做类型转换,再进行值的比较,全等运算符不会做类型转换

  • null 和 undefined 比较,相等操作符(==)为true,全等为false

除了在比较对象属性为null或者undefined的情况下,我们可以使用相等操作符==,其他情况建议一律使用全等操作符===;

Javascript中的事件模型如何理解?

====================================================================================

事件模型可以分为三种:

  • 原始事件模型(DOM0级)

  • 标准事件模型(DOM2级)

  • IE事件模型(基本不用)

点击Javascript中的事件模型查看详情

谈谈你对进程和线程的理解?

============================================================================

多线程可以并行处理任务,但是线程是不能单独存在的,它是由进程来启动和管理的。

一个进程就是一个程序的运行实例。详细解释就是,启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主线程,我们把这样的一个运行环境叫进程。

关系:

  • 进程中的任意一线程执行出错,都会导致整个进程的崩溃。

  • 线程之间共享进程中的数据。

  • 当一个进程关闭之后,操作系统会回收进程所占用的内存。

  • 进程之间的内容相互隔离。

点击到底什么是Event Loop?查看详解

说一说Javascript中事件循环的理解?

=====================================================================================

JavaScript 在设计之初便是单线程,即指程序运行时,只有一个线程存在,同一时间只能做一件事;为了解决单线程运行阻塞问题,JavaScript用到了计算机系统的一种运行机制,这种机制就叫做事件循环(Event Loop)

在JavaScript中,所有的任务都可以分为:

  • 同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行

  • 异步任务:异步执行的任务,比如ajax网络请求,setTimeout定时函数等

同步任务与异步任务的运行流程图如下:

在这里插入图片描述

从上面我们可以看到,同步任务进入主线程,即主执行栈,异步任务进入任务队列,主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。上述过程的不断重复就是事件循环;

点击对Javascript中的事件循环机制的探索和详解查看详解

介绍一下宏任务和微任务

==========================================================================

在这里插入图片描述

解释下什么是事件代理和应用场景?

===============================================================================

是什么:

事件代理,俗地来讲,就是把一个元素响应事件(click、keydown…)的函数委托到另一个元素;

事件流的都会经过三个阶段:捕获阶段 -> 目标阶段 -> 冒泡阶段,而事件委托就是在冒泡阶段完成;

事件委托,会把一个或者一组元素的事件委托到它的父层或者更外层元素上,真正绑定事件的是外层元素,而不是目标元素

当事件响应到目标元素上时,会通过事件冒泡机制从而触发它的外层元素的绑定事件上,然后在外层元素上去执行函数

应用场景:

如果我们有一个列表,列表之中有大量的列表项,我们需要在点击列表项的时候响应一个事件,如果给每个列表项一一都绑定一个函数,那对于内存消耗是非常大的,这时候就可以事件委托,把点击事件绑定在父级元素ul上面,然后执行事件的时候再去匹配目标元素

点击事件代理和应用场景查看详情

什么是函数柯里化?

========================================================================

是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

把接受多个参数的函数转换成接受一个单一参数的函数

// 普通函数

var add = function(x, y) {

return x + y;

}

add(3, 4) //7var foo = ‘bar’;

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
img

Vue 编码基础

2.1.1. 组件规范

2.1.2. 模板中使用简单的表达式

2.1.3 指令都使用缩写形式

2.1.4 标签顺序保持一致

2.1.5 必须为 v-for 设置键值 key

2.1.6 v-show 与 v-if 选择

2.1.7 script 标签内部结构顺序

2.1.8 Vue Router 规范

Vue 项目目录规范

2.2.1 基础

2.2.2 使用 Vue-cli 脚手架

2.2.3 目录说明

2.2.4注释说明

2.2.5 其他

CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

起的朋友,同时减轻大家的负担。**
[外链图片转存中…(img-z5FoSusA-1711893588298)]
[外链图片转存中…(img-nqDLkgss-1711893588299)]
[外链图片转存中…(img-Obr2qPoO-1711893588299)]
[外链图片转存中…(img-m9S3leNB-1711893588299)]
[外链图片转存中…(img-xXaFuSeE-1711893588300)]
[外链图片转存中…(img-ZumeqygD-1711893588300)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-MYqh9NaB-1711893588300)]

Vue 编码基础

2.1.1. 组件规范

2.1.2. 模板中使用简单的表达式

2.1.3 指令都使用缩写形式

2.1.4 标签顺序保持一致

2.1.5 必须为 v-for 设置键值 key

2.1.6 v-show 与 v-if 选择

2.1.7 script 标签内部结构顺序

2.1.8 Vue Router 规范

Vue 项目目录规范

2.2.1 基础

2.2.2 使用 Vue-cli 脚手架

2.2.3 目录说明

2.2.4注释说明

2.2.5 其他

CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值