【面试题】常见前端基础面试题(HTML,CSS,JS)

您所在的位置:网站首页 js的变量提升面试题 【面试题】常见前端基础面试题(HTML,CSS,JS)

【面试题】常见前端基础面试题(HTML,CSS,JS)

2024-07-12 03:24| 来源: 网络整理| 查看: 265

box-sizeing: content-box表示标准盒模型(默认值)

box-sizeing: border-box表示IE盒模型(怪异盒模型)

怎么让一个 div 水平垂直居中

通过 verticle-align:middle 实现垂直居中

通过父元素设置伪元素 :before ,然后设置子元素 verticle-align:middle 实现垂直居中

通过绝对定位实现垂直居中

通过 transform 实现垂直居中

使用弹性盒子居中

BFC

所谓 BFC,指的是一个独立的布局环境,BFC 内部的元素布局与外部互不影响。

触发 BFC 的方式有很多,常见的有:

设置浮动

overflow 设置为 auto、scroll、hidden

positon 设置为 absolute、fixed

常见BFC的应用

解决浮动元素令父元素高度坍塌的问题

解决非浮动元素被浮动元素覆盖问题

解决外边距垂直方向重合问题

JS 的基本数据类型有哪些?基本数据类型和引用数据类型的区别 基本数据类型

JavaScript共有八种数据类型,分别是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt

这些数据可以分为原始数据类型和引用数据类型:

栈:原始数据类型(Undefined、Null、Boolean、Number、String)

堆:引用数据类型(对象、数组和函数)

基本数据类型和引用数据类型的区别

访问方式:

原始值:访问到的是值

引用值:访问到的是引用地址 (js不允许直接访问保存在堆中的对象、首先得到在堆中的地址,然后按照这个地址去获得对象的值)

比较方式:

原始值:比较的是值

引用值: 比较的是引用的地址

变量赋值:

原始值赋值:赋值的是新值,与原来互不影响

引用值赋值:赋值的是地址,指向原值所在堆内存中的地址

动态属性:

原始值:赋值的是值

引用值:赋值的是地址

ES6 新增哪些东西

箭头函数

字符串模板

支持模块化(import、export)

类(class、constructor、extends)

let、const 关键字

新增一些数组、字符串等内置构造函数方法,例如 Array.from、Array.of 、Math.sign、Math.trunc 等

新增一些语法,例如扩展操作符、解构、函数默认参数等

新增一种基本数据类型 Symbol

新增元编程相关,例如 proxy、Reflect

Set 和 Map 数据结构

Promise

Generator 生成器

let const var 的区别?什么是块级作用域?如何用?

var 定义的变量,是函数作用域,没有块的概念,可以跨块访问, 不能跨函数访问,有变量提升。

let 定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问,无变量提升,不可以重复声明。

const 用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改,无变量提升,不可以重复声明。

var不存在暂时性死区,let和const存在暂时性死区

let和const创建的全局变量没有给window设置相应的属性

暂时性死区:使用 let / const 命令声明变量之前,该变量都是不可用的

箭头函数与普通函数的区别

箭头函数没有自己的this、会捕获其所在的上下文的this值,作为自己的this值

箭头函数继承来的this指向永远不会改变

call()、apply()、bind()等方法不能改变箭头函数中this的指向

箭头函数是匿名函数,不能作为构造函数,不能使用new

箭头函数没有自己的arguments

箭头函数没有prototype(原型)

箭头函数不能用作Generator函数,不能使用yeild关键字

bind,apply,call三者的区别

三者都可以改变函数的this对象指向

三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefined或null,则默认指向全局window

三者都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入

bind是返回绑定this之后的函数,apply、call 则是立即执行

是否了解 JavaScript 中的包装类型?

包装对象 : 就是当基本类型以对象的方式去使用时,JavaScript 会转换成对应的包装类型,相当于 new 一个对象,内容和基本类型的内容一样,然后当操作完成再去访问的时候,这个临时对象会被销毁,然后再访问时候就是 undefined

代码理解:

var str = 'hello'; str.number = 10; //假设我们想给字符串添加一个属性 number ,后台会有如下步骤 ( var _str = newString('hello'); // 1 找到对应的包装对象类型,然后通过包装对象创建出一个和基本类型值相同的对象 _str.number = 10; // 2 通过这个对象调用包装对象下的方法 但结果并没有被任何东西保存 _str =null; // 3 这个对象又被销毁 ) console.log(str.number); // undefined 当执行到这一句的时候,因为基本类型本来没有属性,后台又会重新重复上面的步骤 ( var str = newString('hello');// 1 找到基本包装对象,然后又新开辟一个内存,创建一个值为 hello 对象 str.number = undefined;// 2 因为包装对象下面没有 number 这个属性,所以又会重新添加,因为没有值,所以值是未定义;然后弹出结果 str =null; // 3 这个对象又被销毁 ) 复制代码 JS 中如何进行数据类型的转换?

类型转换可以分为两种,隐性转换和显性转换

显性转换

主要分为三大类:数值类型、字符串类型、布尔类型

三大类的原始类型值的转换规则我就不一一列举了,更多详情文章链接 👉 juejin.cn/post/695617…

数值类型(引用类型转换) Number({a: 1}) // NaNNumber([1, 2, 3]) // NaNNumber([5]) // 5 第一步,调用对象自身的`valueOf`方法。如果返回原始类型的值,则直接对该值使用`Number`函数,不再进行后续步骤。 第二步,如果`valueOf`方法返回的还是对象,则改为调用对象自身的`toString`方法。如果`toString`方法返回原始类型的值, 则对该值使用`Number`函数,不再进行后续步骤。 第三步,如果`toString`方法返回的是对象,就报错。 补充一点:`valueOf`和`toString`方法,都是可以自定义的 复制代码 字符串类型(引用类型转换) String({a: 1}) // "[object Object]"String([1, 2, 3]) // "1,2,3"`String`方法背后的转换规则,与`Number`方法基本相同,只是互换了`valueOf`方法和`toString`方法的执行顺序。 复制代码 隐性转换 类型转换前转换后number44string“1”1string“”0booleantrue1booleanfalse0undefinedundefinedNaNnullnull0

详情看上方👆文章链接

闭包

闭包是指有权访问另一个函数作用域中的变量的函数 ———— 《JavaScript高级程序设计》

闭包用途:

能够访问函数定义时所在的词法作用域(阻止其被回收)

私有变量化

模拟块级作用域

创建模块

闭包缺点:闭包调用函数的变量,并且这个变量在函数执行完之后,不能释放,会导致函数的变量一直保存在内存中,过多的闭包可能会导致内存泄漏。

解决:变量设置成null

原型和原型链 原型

每个对象都有一个 proto 属性,该属性指向自己的原型对象

每个构造函数都有一个 prototype 属性,该属性指向实例对象的原型对象

原型对象里的 constructor 指向构造函数本身

原型链

当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾null

作用域和作用域链的理解 作用域

(1)全局作用域

最外层函数和最外层函数外面定义的变量拥有全局作用域

所有未定义直接赋值的变量自动声明为全局作用域

所有window对象的属性拥有全局作用域

全局作用域有很大的弊端,过多的全局作用域变量会污染全局命名空间,容易引起命名冲突。

(2)函数作用域

函数作用域声明在函数内部的变零,一般只有固定的代码片段可以访问到

作用域是分层的,内层作用域可以访问外层作用域,反之不行

(3)块级作用域

使用ES6中新增的let和const指令可以声明块级作用域,块级作用域可以在函数中创建也可以在一个代码块中的创建(由{ }包裹的代码片段)

let和const声明的变量不会有变量提升,也不可以重复声明

在循环中比较适合绑定块级作用域,这样就可以把声明的计数器变量限制在循环内部。

作用域链

在当前作用域中查找所需变量,但是该作用域没有这个变量,那这个变量就是自由变量。

如果在自己作用域找不到该变量就去父级作用域查找,依次向上级作用域查找,直到访问到window对象就被终止,这一层层的关系就是作用域链。

作用域链有一个非常重要的特性,那就是作用域中的值是在函数创建的时候,就已经被存储了,是静态的。

防抖和节流

我们在平时开发的时候,会有很多场景会频繁触发事件,比如说搜索框实时发请求,onmousemove、resize、onscroll 等,有些时候,我们并不能或者不想频繁触发事件,这时候就应该用到函数防抖和函数节流。

函数防抖(debounce),指的是短时间内多次触发同一事件,只执行最后一次,或者只执行最开始的一次,中间的不执行。

函数节流(throttle),指连续触发事件但是在 n 秒中只执行一次函数。即 2n 秒内执行 2 次… 。节流如字面意思,会稀释函数的执行频率。

区别在于:防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行

宏任务和微任务

常见的宏任务有:setTimeout、setInterval、requestAnimationFrame、script等。

常见的微任务有:new Promise( ).then(回调)、MutationObserver 等。

宏任务和微任务的执行流程,总结起来就是:

js在调用时,优先取出微任务,并且在执行过程中如果创建了新的作业,则放在本次执行完后紧接着调用,微任务执行完成后,再取出宏任务执行

哪些情况会导致内存泄漏

以下四种情况会造成内存的泄漏:

意外的全局变量: 由于使用未声明的变量,而意外的创建了一个全局变量,而使这个变量一直留在内存中无法被回收。

被遗忘的计时器或回调函数: 设置了 setInterval 定时器,而忘记取消它,如果循环函数有对外部变量的引用的话,那么这个变量会被一直留在内存中,而无法被回收。

脱离 DOM 的引用: 获取一个 DOM 元素的引用,而后面这个元素被删除,由于一直保留了对这个元素的引用,所以它也无法被回收。

闭包: 不合理的使用闭包,从而导致某些变量一直被留在内存当中。

请介绍一下 JavaScript 中的垃圾回收站机制

JavaScript 具有自动垃圾回收机制。垃圾收集器会按照固定的时间间隔周期性的执行。

JavaScript 常见的垃圾回收方式:标记清除、引用计数方式。

标记清除方式:

工作原理:当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。

工作流程:

垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记;

去掉环境中的变量以及被环境中的变量引用的变量的标记;

被加上标记的会被视为准备删除的变量;

垃圾回收器完成内存清理工作,销毁那些带标记的值并回收他们所占用的内存空间。

引用计数方式:

工作原理:跟踪记录每个值被引用的次数。

工作流程:

声明了一个变量并将一个引用类型的值赋值给这个变量,这个引用类型值的引用次数就是 1;

同一个值又被赋值给另一个变量,这个引用类型值的引用次数加 1;

当包含这个引用类型值的变量又被赋值成另一个值了,那么这个引用类型值的引用次数减 1;

当引用次数变成 0 时,说明没办法访问这个值了;

当垃圾收集器下一次运行时,它就会释放引用次数是 0 的值所占的内存。

防抖,节流是什么 最后

作原理:当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。

工作流程:

垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记;

去掉环境中的变量以及被环境中的变量引用的变量的标记;

被加上标记的会被视为准备删除的变量;

垃圾回收器完成内存清理工作,销毁那些带标记的值并回收他们所占用的内存空间。

引用计数方式:

工作原理:跟踪记录每个值被引用的次数。

工作流程:

声明了一个变量并将一个引用类型的值赋值给这个变量,这个引用类型值的引用次数就是 1;

同一个值又被赋值给另一个变量,这个引用类型值的引用次数加 1;

当包含这个引用类型值的变量又被赋值成另一个值了,那么这个引用类型值的引用次数减 1;

当引用次数变成 0 时,说明没办法访问这个值了;

当垃圾收集器下一次运行时,它就会释放引用次数是 0 的值所占的内存。

防抖,节流是什么 最后



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3