2023Javascript面试题

JavaScrip组成

ECMAScript(核心):JavaScript 语言基础
DOM(文档对象模型):规定了访问HTML和XML的接口
BOM(浏览器对象模型):提供了浏览器窗口之间进行交互的对象和方法
window对象,screen对象 ,location对象,navigator对象,history对象

垃圾回收机制

标记清除算法
引用计数算法

浏览器内核

IE浏览器内核:Trident内核,也是俗称的IE内核;
Firefox浏览器内核:Gecko内核,俗称Firefox内核;
苹果Safari浏览器内核:Webkit内核
Chrome浏览器内核:Blink内核;

stopPropagation和PreventDefault区别

stopPropagation:阻止捕获和冒泡阶段中当前事件的进一步传播。
preventDefault:阻止浏览器做出默认操作。

defer和async区别

• defer并行加载js文件,会按照页面上script标签的顺序执行
• async并行加载js文件,下载完成立即执行,不会按照页面上script标签的顺序执行

输入url到页面加载发生了什么

浏览器查找当前URL是否存在缓存,并比较缓存是否过期
DNS解析URL对应的IP
根据IP建立TCP连接(三次握手)
发送HTTP请求
服务器处理请求,浏览器接受HTTP响应
浏览器解析并渲染页面
关闭TCP连接(四次握手)

浏览器的渲染过程

• 解析HTML构建 DOM(DOM树),并行请求 css/image/js
• CSS 文件下载完成,开始构建 CSSOM(CSS树)
• CSSOM 构建结束后,和 DOM 一起生成 Render Tree(渲染树)
• 布局(Layout):计算出每个节点在屏幕中的位置
• 显示(Painting):通过显卡把页面画到屏幕上

DOM树 和 渲染树 的区别:

• DOM树与HTML标签一一对应,包括head和隐藏元素
• 渲染树不包括head和隐藏元素,大段文本的每一个行都是独立节点,
每一个节点都有对应的css属性

DOM操作——添加、移除、移动、复制、创建和查找节点

(1)创建新节点

createDocumentFragment() //创建一个DOM片段createElement() //创建一个具体的元素createTextNode() //创建一个文本节点

(2)添加、移除、替换、插入

appendChild()removeChild()replaceChild()insertBefore() //在已有的子节点前插入一个新的子节点

(3)查找

getElementsByTagName() //通过标签名称getElementsByName() // 通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)getElementById() //通过元素Id,唯一性

遍历A节点的父节点下的所有子节点

document.getElementById("a").parentNode.children

说一下事件代理?

事件委托是指将事件绑定到目标元素的父元素上,利用冒泡机制触发该事件
addEventListener()
第三个参数为true就在捕获过程中执行,反之就在冒泡过程中执行处理函数

let const var 区别

var
存在变量提升
可以重复声明
在函数中使用var声明变量的时候,该变量是局部的
let
不存在变量提升,let声明变量前,该变量不能使用(暂时性死区)
let命令所在的代码块内有效,在块级作用域内有效
let不允许在相同作用域中重复声明,注意是相同作用域,不同作用域有重复声明不会报错
const
const声明一个只读的变量,声明后,值就不能改变
const必须初始化
const并不是变量的值不能改动,而是变量指向的内存地址所保存的数据不得改动

变量提升

javaScript在执行之前会先进行预编译,主要做两个工作:

  1. 将全局作用域或者函数作用域内所有函数声明提前
  2. 将全局作用域或者函数作用域内所有var声明的变量提前声明,并赋值为undefined

js基本数据类型和引用数据类型

基本类型包括number、string、boolean、undefined,null,Symbol,bigInt
引用类型包括Function和Object
区别是值类型和引用类型的区别是,值类型赋的变量直接存储数据,引用类型的变量存储数据的引用
判断类型方法有

  1. typeof
  2. constructor
  3. instanceof
  4. Object.prototype.toString.call()

typeof 返回数据格式:

基本数据类型:number,string,boolean,undefined,bigint,symbol
引用数据类型:object,function
特别注意:Array和null返回的都是object

instanceof

instanceof 判断对象的原型链上是否存在构造函数的原型。只能判断引用类型。
instanceof 常用来判断 A 是否为 B 的实例

== 的隐式转换规则

undefined、null 自身相等且互相相等

null和undefined的区别

都表示“没有”,null表示引用类型的对象为空,undefined表示变量未定义。
null表示对象空指针,undefined表示变量未定义。
类型不同
typeof null // ‘object’
typeof undefined // ‘undefined’
Number(null) // 0
Number(undefined) // NaN

三个强制转换

Number():
只要有字符,就是NaN
true为1,false,null,““为0
String()
Boolean():””,0,undefined,null,NaN,false这些值时,就会变为false,除此之外强转都是true

数组常用的方法

push: 末尾添加,返回数组新长度,改变原数组
pop: 删除末元素,返回被删除项,改变原数组
unshift:前面添加,返回数组新长度,改变原数组
shift:头部删除,返回被删除项,改变原数组
splice:删除/添加,返回被删除的项目,改变原数组
slice:截取,不会改变原数组
forEach:arr.forEach(function(item,index)){}
filter:返回过滤的新数组,原数组不变
map:返回新数组,原数组不变
some: 相当于逻辑关系中的或(||),只要有一个参数满足条件,就会中断逻辑,返回true,遍历结束,没有找到合适的参数,就返回false
ever: 相当于逻辑关系中的且(&&),只有所有参数满足条件的时候,才会返回true,如果有一个不满足,就会逻辑中断,返回false,
reduce:
flat:
sort:
reverse:

forin,forof,foreach,map区别

for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性),可以用hasOwnProperty()识别出继承属性,
for...of根据值遍历
for...of用来遍历数据,例如数组中的值,但是也可以遍历字符串,支持Map和Set对象的遍历,
避免了所有for...in的弊端,与forEach相比可以正确响应breakcontinuereturn语句。
forEach根据index遍历
forEach一般只能适用于数组,功能是从头到尾把数组遍历一遍,可以有三个参数,后两个可以不写
v,i,a;//分别对应:数组元素,元素的索引,数组本身
和forEach相比,使用方法一样有三个参数,map只能对元素进行加工处理,产生一个新的数组对象

Object.keys,Object.getOwnPropertyNames

Object.keys 返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
Object.getOwnPropertyNames 返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。

函数表达式和函数声明有什么区别

函数声明会提升,函数表达式则不会,因此函数声明之前可以正常调用,但函数表达式之前调用函数则会报错。

闭包

闭包的实质是因为函数嵌套而形成的作用域链
闭包的定义即:函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数 B 就是闭包

函数防抖与节流

在前端开发中一部分的用户行为会频繁的出发事件执行,对DOM操作、
资源加载等耗费性能的处理,很可能导致界面卡顿,甚至浏览器的崩溃。
函数防抖(debounce)和函数节流(throttle)就是为了解决类似的需求应运而生的。
防抖
函数防抖就是在函数需要频繁触发情况时,只有足够空闲的时间,才执行一次。
• 函数节流(throttle)是指阻止一个函数在很短时间间隔内连续调用。
只有当上一次函数执行后达到规定的时间间隔,才能进行下一次调用。
但要保证一个累计最小调用间隔(否则拖拽类的节流都将无连续效果)
• 函数节流用于 onresize, onscroll 等短时间内会多次触发的事件
• 函数节流的原理:使用定时器做时间节流。
当触发一个事件时,先用 setTimout 让这个事件延迟一小段时间再执行。
如果在这个时间间隔内又触发了事件,就 clearTimeout 原来的定时器,
再 setTimeout 一个新的定时器重复以上流程

事件循环机制吗?

代码开始执行,创建一个全局调用栈,script作为宏任务执行
执行过程过同步任务立即执行,异步任务根据异步任务类型分别注册到微任务队列和宏任务队列
同步任务执行完毕,查看微任务队列
若存在微任务,将微任务队列全部执行(包括执行微任务过程中产生的新微任务)
若无微任务,查看宏任务队列,执行第一个宏任务,宏任务执行完毕,查看微任务队列,重复上述操作,直至宏任务队列为空

宏任务:由浏览器规定的
setTimeout
setInterval
Ajax
DOM事件
微任务:由ES6语法规定的
Promise
async

setTimeout、promise、async/await 的区别

主要考的是JS队列加载的问题,三者的排序是:promise>async>setTimeout
setTimeout属于延迟方法,会被放倒最后,也就是主线程空闲的时候才会触发
Promise本身是同步的,但在执行resolve或者rejects时是异步的,即then方法是异步的
setTimeout属性宏任务,Promise里面的then方法属于微任务,Async/Await中await语法后面紧跟的表达式是同步的,但接下来的代码是异步
的,属于微任务

Promise.all,Promise.race区别

Promise.all() 全部promise成功才算成功,一个promise就算失败,成功的话,返回成功的数据数组,失败的话抛出最先失败的promise的reason。
Promise.race() 最先的promise完成则返回,promise结果和最先完成的promise一致。

Promise.all(promises: Iterable<Promise>): Promise<Array>
Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中  promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果

Promise.race(promises: Iterable<Promise>): Promise
Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

查询某个对象是否有某个属性的方法

使用in关键字
该方法可以判断对象的自有属性和继承来的属性是否存在。
使用对象的hasOwnProperty()方法
该方法只能判断自有属性是否存在,对于继承属性会返回false。
使用undefined判断
自有属性和继承属性均可判断。

var o={x:1};
o.x!==undefined;    //true
o.y!==undefined;    //false
o.toString!==undefined  //true

该方法存在一个问题,如果属性的值就是undefined的话,该方法不能返回想要的结果,如下:

var o={x:undefined};
o.x!==undefined;    //false,属性存在,但值是undefined
o.y!==undefined;    //false
o.toString!==undefined  //true

删除对象中某个属性

delete

`delete`操作符返回一个布尔值: `true`指删除成功,否则返回`false`. 但是通过 `var`, `const``let` 关键字声明的变量无法用 `delete` 操作符来删除

return

return 可以返回一个数据给函数运行的外面
如果函数没有使用return或者直接使用return,后面没有值,这时候实际是返回一个undefined

原型和原型链

在js中,所有对象都是Object的实例,并继承Object.prototype的属性和方法,但是有一些是隐性的。
所有的引用类型(包括数组,对象,函数)都具有
对象特性,可自由扩展属性。
隐性原型属性(proto),值也是一个普通的对象。
.所有的函数,都有一个prototype属性,值也是一个普通的对象。
所有的引用类型的__proto__属性值都指向构造函数的prototype属性值。
当试图获取对象属性时,如果对象本身没有这个属性,那就会去他的__proto__(prototype)中去寻找。

Object.__proto__
ƒ () { [native code] }
Function.__proto__
ƒ () { [native code] }
原型链的终点:Object.prototype

2023Javascript面试题_第1张图片

new一个对象发生了什么

  1. 创建了一个空的js对象(即{})
  2. 将空对象的原型prototype指向构造函数的原型
  3. 将空对象作为构造函数的上下文(改变this指向)
  4. 判断构造函数的返回值,以决定最终返回的结果。
    a. 如果返回值是基础数据类型,则忽略返回值;
    b. 如果返回值是引用数据类型,则使用return 的返回,也就是new操作符无效;

继承的多种方式和优缺点

https://juejin.cn/post/6844903477819211784
1.原型链继承(引用类型的属性被所有实例共享,在创建 Child 的实例时,不能向Parent传参)
2.借用构造函数(经典继承)
优点:
1.避免了引用类型的属性被所有实例共享
2.可以在 Child 中向 Parent 传参
缺点:
方法都在构造函数中定义,每次创建实例都会创建一遍方法。
3.组合继承
原型链继承和经典继承双剑合璧。
4.原型式继承
5. 寄生式继承
6. 寄生组合式继承

深拷贝,浅拷贝

如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
深拷贝:会拷贝所有层级(递归,Json.parse(Json.stringify()),JQ的extend)
$.extend( [deep ], target, object1 [, objectN ] )
deep表示是否深拷贝,为true为深拷贝,为false,则为浅拷贝
target Object类型 目标对象,其他对象的成员属性将被附加到该对象上。
object1 objectN可选。 Object类型 第一个以及第N个被合并的对象。
浅拷贝:扩展运算符,Object.assign()

ajax,promise,axios,fetch区别

Ajax 指的是 XMLHttpRequest(XHR),核心使用XMLHttpRequest对象,多个请求之间如果,有先后关系的话,就会出现回调地狱。实现页面局部刷新
promise解决异步回调嵌套
axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,本质上也是对原生XHR的封装,
只不过它是Promise的实现版本,符合最新的ES规范,解决回调地狱
fetch号称是AJAX的替代品,是在ES6出现的,使用了ES6中的promise对象。
Fetch是基于promise设计的,Fetch的代码结构比起ajax简单多了,参数有点像jQuery ajax。但是,一定记住fetch不是ajax的进一步封装,而是原生js,没有使用XMLHttpRequest对象。

hash与history区别

1.hash路由在地址栏URL上有#,用 window.location.hash 读取。
而history路由没有会好看一点
2.我们进行回车刷新操作,hash路由会加载到地址栏对应的页面
而history路由一般就404报错了(刷新是网络请求,没有后端准备时会报错)
3.hash路由支持低版本的浏览器,而history路由是HTML5新增的API。
4.hash的特点在于它虽然出现在了URL中,但是不包括在http请求中,所以对于后端是没有一点影响的,所以改变hash不会重新加载页面,所以这也是单页面应用的必备。
5.history运用了浏览器的历史记录栈,之前有back,forward,go方法
6.history的这种模式需要后台配置支持。比如:当我们进行项目的主页的时候,一切正
常,可以访问,但是当我们刷新页面或者直接访问路径的时候就会返回404,那是因为在
history模式下,只是动态的通过js操作window.history来改变浏览器地址栏里的路径,并
没有发起http请求,但是当我直接在浏览器里输入这个地址的时候,就一定要对服务器
发起http请求,但是这个目标在服务器上又不存在,所以会返回404

get与post区别

GET把参数包含在URL中,POST通过request body传递参数
GET请求只能进行url编码,而POST支持多种编码方式
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
get请求可以被缓存,post不可以被缓存
get后退不会有影响,post后退会重新进行提交
get传递数据是通过URL进行传递,对传递的数据长度是受到URL大小的限制,
URL最大长度是2048个字符。post没有长度限制

CommonJS, AMD, CMD,UMD,ES6模块规范区别

es6:module.exports {...});
// 加载模块
require(["module", "../app"], function(module, app) {...});
异步模块加载规范,模块的加载不影响后面语句的运行

return,break,continue的区别

return:只能使用在函数中,直接跳出函数,不执行return以后的语句
break:只能使用在循环或者switch中,跳出当前循环,不执行break以后语句,并且不再进入函数
continue:只能使用在循环中,跳出本次循环,当前不再继续执行continue后面的语句,但是继续下一次循环

map

arr.map(function callback(currentValue, index, array],thisArg)
callback 生成新数组元素的函数使用三个参数:
currentValue 数组中正在处理的当前元素。
index 数组中正在处理的当前元素的索引。 可选
array map 方法调用的数组
thisArg可选

parsInt

parseInt(string,radix)
parseInt的参数包含两个:
string字符串,若传入的string不是字符串,则会默认使用tostring()函数来将传入的内容转化为字符串。
字符串以数字开头
若字符串前有空格,空格会被去除
字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分。
若传入的string不是字符串,则会默认使用tostring()函数来将传入的内容转化为字符串。
若字符串以0x或0X开头则以16进制解析。
若字符串以0开头则以10进制解析。
若传入的为数字,且开头为0,则以八进制解析。
若传入值以0b或0B开头(不加引号),则以二进制解析
科学计数法表示的数会被当成字符串来解析
若传入字符串不是一数字开头,则返回NaN。

radix被解析值的进制,该参数可以选择传入(其默认值为10),其值应在2~36之间,返回值只有两种可能:1、一个十进制整数 2、NaN
第二个参数不是数值,会被自动转为一个整数。这个整数只有在2到36之间,才能得到有意义的结果,超出这个范围,则返回NaN。如果第二个参数是0、undefined和null,则直接忽略。
解析的字符串包含的数字超过 基数,返回NaN

Math

Math.round() 函数返回一个数字四舍五入后最接近的整数。
x = Math.round(20.49);   //20
x = Math.round(20.5);    //21
x = Math.round(-20.5);   //-20
x = Math.round(-20.51);  //-21

Math.ceil() 函数总是四舍五入并返回大于等于给定数字的最小整数。
console.log(Math.ceil(.95));// Expected output: 1
console.log(Math.ceil(4));// Expected output: 4
console.log(Math.ceil(7.004));// Expected output: 8
console.log(Math.ceil(-7.004));// Expected output: -7

Math.random() 函数返回一个浮点型伪随机数字,在0(包括 0)和1(不包括)之间。

Math.floor(小于等于 x 的最大整数。它的值与 -Math.ceil(-x) 相同

export和export default的区别

export default xxx
import xxx from ‘./’
export xxx
import {xxx} from ‘./’

中断ajax请求

设置超时时间让ajax自动断开,
手动停止ajax请求,其核心是调用XML对象的abort方法,ajax.abort()

href

标签中href="javascript:;"表示什么意思?
javascript:是表示在触发默认动作时,执行一段JavaScript代码,
而 javascript:; 表示什么都不执行,这样点击时就没有任何反应。

1 + - + + + - + 1的结果

1+ (-++±) + 1

前端性能优化方法

1、请求数据阶段主要指标是服务器响应时间,从服务器角度优化。
2、加载和解析页面阶段,性能优化的主要思路是减少请求数量、降低资源的大小和避免阻塞。
3、渲染阶段优化思路是避免重绘和重排。

类中的静态变量,静态方法

静态方法被设计为只能被创建它们的构造器使用,不能被实例使用

string特殊点

String.prototype.giveLydiaPizza = () => {
  return 'Just give Lydia pizza already!'
}

const name = 'Lydia'
- A: `"Just give Lydia pizza already!"`
- B: `TypeError: not a function`
- C: `SyntaxError`
- D: `undefined`
name.giveLydiaPizza()
A

String 是内置的构造函数,我们可以向它添加属性。我只是在它的原型中添加了一个方法。基本类型字符串被自动转换为字符串对象,由字符串原型函数生成。因此,所有 string(string 对象)都可以访问该方法!

object特殊点

const a = {}
const b = { key: 'b' }
const c = { key: 'c' }

a[b] = 123
a[c] = 456

console.log(a[b])
- A: `123`
- B: `456`
- C: `undefined`
- D: `ReferenceError`

对象的键被自动转换为字符串。我们试图将一个对象 `b` 设置为对象 `a` 的键,且相应的值为 `123`。

然而,当字符串化一个对象时,它会变成 `"[object Object]"`。因此这里说的是,`a["[object Object]"] = 123`。然后,我们再一次做了同样的事情,`c` 是另外一个对象,这里也有隐式字符串化,于是,`a["[object Object]"] = 456`。

然后,我们打印 `a[b]`,也就是 `a["[object Object]"]`。之前刚设置为 `456`,因此返回的是 `456`

你可能感兴趣的:(firefox,css,safari)