JS 面试题整理

1、doucment . write() 和 innerHTML 的区别?

document . write( ) 是直接将内容写入页面的内容流,会导致页面全部重绘。

innerhHTML 将内容写入某个 DOM 节点,不会导致页面全部重绘

2、JS 中的数据类型有哪些?

基础数据类型,Boolean , Number , String , Undefined , Null , Symbol

引用数据类型,Object , Array , Function

3、JS 中基本类型和引用类型的区别?

基本数据类型

1、基本类型的变量是存放在栈区的

2、基本类型的比较是值得比较

3、基本类型得赋值在赋值操作后,两个变量是互相不受影响的

引用数据类型

1、引用类型在栈内存中保存的实际上是对象在堆内存中的引用地址

2、引用类型的比较是引用地址的比较

3、引用类型的赋值其实是保存在栈区引用地址的赋值,因此两个变量指向同一个对象,任何的操作都会相互影响

4、JS 中堆栈和队列的区别?

堆栈和队列都是动态的集合

堆栈遵循先进后出的策略。比如 : 数组的 push() 和 pop () 方法,实现类似栈的行为

队列遵循先进先出的策略。比如 : 数组的 shift () 和 unshift () 方法,实现类似队列的行为

5、检测变量的数据类型的方法有哪些?

1、typeof , 可用于检测基本类型 ,但碰到引用类型军返回为 object

2、instanceof , 可用于引用类型的检测 ,但对于基本类型是不生效的

3、constructor , 可用于检测 js 的基本类型和引用类型 , 但当对象的原型更改之后 ,constructor 便失效了

4、Object . prototype . toString . call () , 可用于检测 js 所有的数据类型

6、JS 中 == 和 === 的区别是什么 ?

首先 == 用来检测两个操作数是否相等 ,这里的相等定义的非常宽松,可以允许进行类型转换,只比较操作数的值。

其次 === 用来检测两个操作数是否严格相等,会同时比较操作数的值,操作数的类型,操作数的引用地址。

7、JS 开启严格模式有哪些影响?

变量:不能用 delete 删除变量,会防止意外的声明全局变量

函数:全局函数内的 this 是 undefined ,函数参数不能重名,不能再函数内使用 arguments , caller , arguments , callee

其他: eval 不会为上层引用变量,不能使用 js 未来将会使用的关键字

8、break 和 continue 的区别是什么?

break 和 continue 的区别是,break 是直接结束循环,继续执行循环后的其他语句,而 continue 呢,它是跳过本次循环,继续执行下一次循环。

9、谈一谈你理解的变量提升,函数提升?

提升,简单说就是在 JavaScript 代码执行前 js 引擎会先进性预编译,预编译期间会将变量声明与函数声明提升至其所在作用域的最顶端,函数内声明的变量只会提升至该函数作用域最顶层。

1、对于变量提升,只是提升变量声明,并不会将赋值初始化提升

2、如果声明了同名的变量和函数,函数提升的优先级大于变量,即函数提升在变量提升之上。

10、说一说函数上下文(this)的几种情况?

1、普通函数执行,内部 this 默认是 window ,严格模式下是 undefined

2、对象 . 方法 ( ) 执行,内部 this 是对象本身

3、构造函数用 new 执行内部 this 指向新创建的实例对象

4、箭头函数,箭头函数没有自己的 this ,箭头函数中的 this 是箭头函数创建时当前上下文中的 this 。如果当前上下文没有 this 就会继续向上寻找。

5、事件处理函数:函数中的 this 是当前元素本身

6、函数内部 this 被 call , apply , bind 强制修改,以修改后指向为准

总结:箭头函数是创建时就已经确定了 this ,又由于箭头函数本身没有 this ,所以使用 call 等方法也无法改变其 this 指向,第一个参数将被忽略,普通函数则是执行时才明确 this。

11、说一说 call , apply , bind 的区别?

相同点:

在 JS 中,这三者都是用来改变函数内 this 的指向的,他呢吧的第一个参数都是 this 要指向的对象。如果第一个参数是 null ,则函数内 this 最终会指向 window

不同点:

对于 call ,改变函数内 this 指向时会主动调用函数,如果还需要传其他参数,多个参数只能逗号分割一个一个传入;

对于apply,改变函数内 this 指向时会主动调用函数,如果还去要传其他参数,多个参数以一个数组的形式传入;

对于 bind,改变函数内 this 指向时并不会主动调用函数,而是的返回一个新函数,如果还需要传其他参数,可以像 call 那样传参,由于 bind 的返回值是一个新函数,所以我们还可以在调用新函数的时候再进行传参。

12、JavaScript 中数组的常用方法,至少10个?

会改变数组自身的方法:push , pop , unshift , splice , sort , reverse

不会改变数组自身的方法:cancat , join , slice , tooString

ES5 数组方法:forEach , map , every , some , filter , reduce , indexOf , lastIndexOf

ES6 数组扩展 :from , of , find , findIndex , include

18、ES6 的新特性有哪些?

1、变量声明:新增了 let 和 const

2、模板字符串

3、数据结构:set 、map ,对象键值重名简写,对象合并 Object . assign ( ) ,解构,展开运算符 ...

4、函数:箭头函数,函数的参数默认值

5、类的支持:引入了 class 关键字

6、模块 import , export

7、promise

19、说一说你对箭头函数的了解?

1、箭头函数时匿名函数的简写形式

2、当箭头函数只有一个参数时,可以省略 ( )

3、当箭头函数 { } 中只有一条语句,并且该语句时 return ,则可以省略 { } 和 return

4、箭头函数内部的 this 指向的是上一级作用域中的 this

5、箭头函数内部没有 arguments

6、箭头函数不能通过 new 实例化对象

20、ES7 的新特性有哪些?

数组新增 includes 方法

** 求幂运算符

21、如何理解 JS 中的闭包

碧波啊实际上就是一个能够访问另一个函数作用域中变量的函数

闭包的应用:实现变量的私有化,事件防抖,事件节流,偏函数与柯里化,bind 等等函数

22、JavaScript 中实现异步编程的方式有哪些?

1、回调函数

2、事件监听

3、发布 / 订阅

4、 Promise 对象

23、什么是 Promise ?我们用 Promise 来解决什么问题

Promise 是异步编程的一种解决方案。promise 有三种状态:pending( 等待态 ) , realove ( 成功态 ) , rejected ( 失败态 ) ; 状态一旦改变,就不会再变。创造 promise 实例后,它会立即执行

Promise 用来解决传统异步回调出现的回调地狱问题。

24、ES8 的新特新有哪些,请举例 ?

Object . values / Object . entries

String padding ( 字符串填充 )

Object . getOwnPropertyDescriptors

函数参数列表和调用中的尾逗号 ( Trailing commas )

async / await

25、描述一下 JavaScript 防抖函数的原理?

防抖动是将短时间内的多次执行变为最后一次执行

26、描述一下JavaScript 节流函数的原理?

节流是将短时间按内的多次执行变成每隔一段时间执行一次

27、JavaScript 中实现继承有哪些方案?

原型链继承

构造函数继承

组合继承

寄生式继承

寄生组合式继承

28、什么是原型链,原型链的作用是什么?

每一个对象,都有一个原型对象与之关联,则个原型对象它也是一个普通对象,这个普通对象也有自己的原型对象,这样层层递进,就形成了一个链条,这个链条就是原型链。

通过原型链可以实现 JS 的继承,把父类的原型对象赋值给子类的原型,这样子类实例就可以访问父类原型上的方法了。

29、Object 原型上有哪些方法?

1、constructor

2、hasOwnProperty()

3、isPrototypeOf()

4、valueOf()

5、toString()

6、toLocaleString()

30、浏览器端 event loop 工作流程( 原理 ) 是什么?

1、js 中有同步任务、异步任务两种

2、同步任务在 JS 引擎线程执行,形成执行栈

3、执行栈中的同步任务在执行过程中遇到异步任务,异步任务被房屋任务队列,等待执行

4、执行栈中的任务运行完成后( JS 引擎空闲 ) ,从任务队列中读取异步任务,加入到执行栈,并执行

5、主线程不断重复上面的第三步

31、请描述一下 JavaScript 中的异步任务?

异步任务分为宏任务,微任务

宏任务:script ( 整体代码 ) ,setTimeout , setInterval , setInterval , setImmediate , I / O , UI rendering

微任务:process , nextTick ( Nodejs ) , Promises , Object . observe , MutationObserver ;

当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同义词事件循环中,微任务永远在宏任务之前执行。

32、原生 js 中获取元素节点的方法有哪些?

通过元素类型的方法来获取

getElementById ( )

getElementsByTagName ( )

getElementsByClassName ( )

querySelector ( )

querySelectorAll ( )

getElementsByName ( )

根据节点关系来获取

parentElement

children

firstElementChild

lastElementChild

nextElementSibling

previousElementSibling

根据特殊属性来获取

document . title

document . body

document . images

document . forms

33、实现一个栈数据结构,结合栈先进后出的特性,模拟实现 in , out , top , size 函数

in :保存数据到栈结构中

out :删除栈结构最顶部的值,并返回该值

top :获取并返回栈结构最顶部的值

size :获取栈结构中数据的个数并返回

思路:用数组模拟栈结构

class Stack{
  constructor(){
    this.arr[];
  }


in(val){
  this.arr.push(val);
}

out(){
  return this.arr.pop()
}

top(){
  return this.arr[this.arr.length-1]
}

size(){
  return this.arr.length;
}
}

34、请说一下innerHTML 和 innerText 的区别?

区别:

取值时 innerText 只会获取节点里面的文本薪资,而 innerHTML 会获取节点下面的所有内容,包括标签本身。

设置值时 innerText 会把 html 标签当作普通的文本,原样显示,而 innerHTML 会将标签解析成节点

35、请说一下 i++ 和 ++i 的区别?

区别:

i ++ 和 ++i 都可以让变量 i 的值加 1

i ++ 表达式的值是变量 i 加 1 之前的值

++i 表达式的值是变量 i 加1 之后的值

36、伪数组转数组饿方式有哪些?

方式一:[ ...伪数组 ]

方式二:Array . from( 伪数组 )

方式三:Array . prototype . slice . call ( 伪数组 )

37、new 操作符具体干了什么?

1、创建一个空对象,让 this 变量指向该对象,同时还继承了该函数的原型

2、给 this 引用的对象添加属性和方法

3、隐式的返回 this

38、JavaScript 中字符串的常用方法,至少10个?

选取字符串:substr , substring , slice

查询字符串:indexOf , includes ,search , match

其他:split , replace , chartAt , toLowercase , toUppercase , trim

39、DOM 0 和 DOM 2 两种事件模型的区别?

DOM 0 事件模型:

1、绑定多个同类型事件,后绑定的事件生效 ( 后绑定的会覆盖前面的 )

2、解除事件绑定:标签 . on事件类型 = null ;

DOM 2 事件模型:

1、可以重复绑定多个同类型事件,都会生效

2、想要解除事件绑定,绑定事件和解除事件绑定函数的第二个参数必须是有名函数的名字

40、请描述一下你理解的事件委托?

所谓的事件委托,就是利用事件冒泡的原理,将原本绑定给内部多个标签的事件,绑定给外层一个公共父标签,当内层标签上触发事件时,该事件会委托给外层公共父标签来处理。

事件委托的好处:

1、减少 DOM 操作,提高性能

2、新添加的元素还会有之前的事件

41、网页中造成内存泄露的原因都有哪些?

1、意外的全局变量( 在函数内部没有使用 var 进行声明的变量 )

2、闭包

3、对象的循环引用

4、未清除的计时器

5、DOM 泄露 ( 获取到 DOM 节点之后,将 DOM 节点删除,但是没有手动释放,拿保存在变量中的 DOM 节点还可以访问到,就会造成泄露 )

42、谈谈你对 this 的理解


this 是 JavaScript 语言的一个关键字,他是函数运行时自动生成的一个内部对象,只能在函数内部使用。

this指的是调用函数的呢个对象,this 的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定 this 到底指向谁,实际上 this 最终指向的是调用它的对象。

43、描述一下 cookies ,sessionStorage 和 localStorage 的区别?

sessionStorage 、 localStorage 、cookie 都是在浏览器端存储数据

sessionStorage 在当前窗口中存储数据。也就是说只要这个浏览器窗口没有关闭,及时出阿信页面或进入同源另一页面,当前数据仍然存在。关闭窗口后,sessionStorage 即被销毁。同时“ 独立 ”打开的不同窗口,即使是同一页面,sessionStorage 对象也是不同的。

localStorage 存储的数据是永久的,除非被手动清除,否则永久保存。

coolies 会发送到服务器端,其余两个不会。

44、var 、let 、 const 的区别是什么?

var , let 声明的是变量 ,let 声明的变量不能重名,用 let 声明的变量,拥有 { } 的块即作用域,是局部变量,只能在 { } 内使用,用 var 声明的变量只有函数级作用域和全局作用域。

const 声明的是常量,必须在声明时初始化,声明后无法修改常量的值。

45、面向对象和面向过程的区别是什么?

面向过程:将需求的实现分为不同的步骤,根据这些步骤去实现需求,在维护、复用、扩展上比较差。

面向对象:将需求分为不同的对象,并给对象赋予属性和行为,多个对象配合实现需求,易维护、易复用、易扩展。

46、js 中深拷贝的实现方法有哪些?

1、JSON . parse ( JSON . stringify ( obj ) )

2、Object . assign( { } , obj ) 当 obj 对象中继续嵌套对象的时候,此方法,也是浅拷贝

3、通过 jQuery 的 extend 方法实现深拷贝 $ . extend ( true , { } , obj )

4、使用对象遍历 + 递归的方式实现深拷贝

47、请说一说什么是作用域?

1、全局作用域:在最外层函数外定义的变量拥有全局作用域,即对任何内部函数来说,都是可以访问的。

2、局部作用域:局部作用域一般指函数大括号所在作用域,函数内部的变量在函数外部是无法访问的。在 ES6 之前,只有函数可以划分变量的作用域,所以在函数的外面无法访问函数内的变量。

3、块级作用域:凡是代码块就可以划分变量的作用域,比如 if 、else 的大括号作用域,这种作用域的规则就叫做块级作用域

块级作用域 、函数作用域 、词法作用域之间的区别:

(1)块级作用域和函数作用域描述的是:什么东西可以划分作用域

(2)词法作用域描述的是 :变量的查找规则

48、什么是作用域链?

作用域链 当代码在一个环境中执行时,会创建变量对象的一个作用域链,由子级作用域返回父级作用域中寻找变量,就叫做作用域链,作用域链中的下一个变量对象来自包含环境,也叫外部环境。而再下一个变量对象则来自下一个包含环境,一直延续到全局执行环境。全局执行环境的变量对象始终都是作用域链中的最后一个对象,作用域链前端始终都是当前执行的代码所在环境的变量对象。

49、dom 结构操作怎样添加、移除、移动、复制、创建、和查找节点?

1、创建新节点:creatElement( ) 创建一个 DOM 片段 createDocumentFragment( ) 创建一个文本节点 createTexenode( )

2、添加 appendChild( ) 、移除 removeChild( ) 、替换replaceChild( ) 、插入 insertBefore( )

3、查找 getElementsByTagName( ) 、getElementsByClassName( ) 、getElementsByName( ) 、getElementById( )

50、For 循环 与 map 循环有什么区别?

For 循环:再固定长度或者长度不计算的情况下 for 循环效率更高

Map 循环:再不确定长度或者计算长度有损性能的时候用 map 比较方便,如果需要操作元素里面的每一个值并且返回一个新数组的话,那么 map 就是最好的选择,数组中的元素为原始数组调用函数处理后的值。

51、事件委托是什么?如何确定事件源?

事件委托还有一个名字叫事件代理 ,JS 高程上将:事件委托就是利用事件冒泡,只定制一个时间处理程序,就可以管理某一类型的所有事件。

将子元素的事情委托给他们的祖先级元素来干,然后使用 event . target ( 低版本 IE 用的是 event . srcElement ) 来代替已经混乱的 this 关键字

解决动态元素 ( 刚进入页面时,元素不在页面内 ) 无法绑定事件问题

再极端情况下可以提升客户端性能

52、字符串与数字显示转换时相关的函数

数字转换成字符串:toString ( ) 、toFixed ( )

字符串转换为数字:Number ( ) 、parseInt ( ) 、parseFloat ( )

52、数字与字符串,隐式转换时的规则

1、字符串加数字,数字就会转为字符串

2、数字与字符串进行减 ( 乘 、除 、大于 、小于 ) 运算时,字符串转成数字。两个字符串也会转成数字。

53、值传递与引用传递的区别?

值传递是单向的传递,只能由实参传递给形参,而不能由形参传递给实参,因为值传递的数据,地址和值是一个内容,所以修改形参的数据不会影响到实参的数据。所以形参的改变不会影响到实参。值传递就是在函数调用中函数内部开辟了空间,结果函数没有改变到外面的值。

引类型传递可以通过改变形参而改变实参。只要任何一个变量指向同一个空间,那么该变量都可以去操作该空间的值,形参如果是一个基本数据类型,形参的改变对实参没有影响;形参如果是一个引用数据类型,形参的改变会直接影响实参。

54、事件绑定方式由哪些?

行内式:直接在代码中添加 JavaScript 代码,以属性的形式写在元素里面;

在 JavaScript 中绑定:元素对象 . 事件名( ) = 匿名函数 ;

或者是 元素对象 . 事件名( ) = 函数名 ;

用监听事件绑定 :元素对象 . addEventListener ( ' 事件名( 不带on ) , 匿名函数 ' )

或者元素对象 . attacheEvent( ' 事件名( 带on ) , 匿名函数 ' )

55、Dom 节点遍历的属性有哪些?

遍历 DOM 节点一般用节点的 childNodes , firstChild , lastChild , nodeType , nodeName , nodeValue 属性。

56、事件监听的好处?

1、可以决定事件流传递是冒泡还是捕获

2、可以为相同的元素,多次绑定相同的事件。

57、事件委托的好处?

减少了事件绑定浏览器重绘的次数,提高了程序的执行效率

减少事件的冗余绑定,节约了事件资源

可以解决动态添加的元素节点无法绑定事件的问题

58、防抖和节流的区别以及应用场景

区别:

函数节流 :连续触发事件但是在n秒中只执行一次函数。比如人的眨眼睛,就是在一定时间内眨一次。

函数防抖:防抖就是指触发事件后在n秒内函数只能执行一次,如果在n秒内又触发了事件,则会重新计算函数执行事件。比如坐公交,就是一定时间内,如果有人陆续刷卡上车,司机就不会开车,只有别人没刷卡了,司机才开车。

应用场景

函数节流:多数在监听页面元素滚动事件的时候会用到。因为滚动事件是一个高频触发的事件

函数防抖:最常见的就是用户注册时候的手机号码验证和邮箱验证。只有等用户输入完毕后,前端才需要检查格式是否正确,如果不正确,再弹出提示语。

59、重绘和回流

渲染:解析 HTML,生成 DOM 树 ,解析 CSS ,生成 CSSOM树,将 DOM 树和 CSSOM 树 结合生成渲染树 ( Render Tree )

回流:当渲染树中的一部分或者全部因为元素的尺寸、布局、隐藏等改变而需要重新构建的时候,这时候就会发生回流。根据生成的渲染树,进行回流,得到节点的几何信息( 位置,大小 )

重绘:在回流的时候,浏览器会使渲染树中受到影响的元素部分失效,并重新绘制这个部分的渲染树,完成回流以后,浏览器会重新绘制受到影响的部分元素到屏幕中,这个过程就是重绘。根据渲染树以及回流得到的几何信息,得到节点的绝对像素。

重绘和回流发生时机:添加或删除可见的 DOM 元素 、元素的位置发生变化 、元素的尺寸发生变化( 包括外边距、内边框、边框大小、高度和宽度等 ) 、内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代 、页面一开始渲染的时候( 这肯定避免不了 ) 、浏览器的串口尺寸变化( 因为回流是根据视口的大小来计算元素的位置和大小的 )

回流一定会触发重绘,而重绘不一定会回流

如何减少回流,重绘?

1、修改 html 元素中对应的 class 名,利用 class 替换样式

2、csstext ( 利用cssText属性合并所有改变,然后一次性写入 )

3、display : none ( 隐藏元素,应用修改 ,重新显示 )

60、同步和异步区别 / 阻塞与非阻塞区别

同步和异步:同步与异步是对应的,他们是线程之间的关系,两个线程之间要么是同步的,要么是异步的。

区别:同步就是由调用者主动等待这个调用的结果。而异步则是相反,调用在发出之后,这个调用就直接返回了,没有返回结果。

同步就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。当一个异步过程调用发出后,调用者不会立刻得到结果,而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。

阻塞与非阻塞:阻塞与非阻塞式对同一个线程来说的,在某个时刻,线程要么处于阻塞,要么处于非阻塞。

区别:阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回

非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

61、请描述一下构造函数 ,实例对象 ,原型对象三者之间的关系?

每个构造函数都可以通过 prototype 指向原型对象,原型对象通过 constructor 指向构造函数,实例对象通过 __proto__指向原型对象

62、js 中当我们执行 obj.foo( ) 调用方法时会发生什么事情?

调用 obj . foo( ) 时:

1、先在对象自身找有没有 foo 方法 ,找到则调用方法

2、没有找到,再去原型对象里找有没有 foo 方法,找到就调用方法

3、没有找到,则沿着原型链继续到原型对象的原型对象上找有没有 foo 方法,找到就调用方法

4、一直到原型链的重点,没有找到就报错了 TypeError : obj . foo is not a function

63、说一说 js 中你所知道的设计模式

单例模式 、工厂模式 、建造者模式 、适配器模式 、装饰器模式 、代理模式 、 策略模式 、观察者模式 、发布订阅模式 、职责链模式 、中介者模式

64、js 中遍历对象属性的方法有哪些?

1、for in : for in 村换遍历对象自身的和继承的可枚举属性 ( 不含Symbol属性 )

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

3、Reflect . ownKeys( obj ) : Reflect . ownKeys 返回一个数组,包含对象自身的( 不含继承的 ) 所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。

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

5、Object . getOwnPropertySymbols ( obj ) : Object . getOwnPropertySymbols 返回一个数组,包含对象自身的所有 Symbol 属性的键名。

以上的5种方法遍历对象的键名,都遵守同样的属性遍历的次序规则。

首先遍历所有的数值键,按照数值升序排列

其次遍历所有字符串键,按照加入时间升序排列

最后遍历所有 Symbol 键,按照加入时间升序排列

65、js 函数种特有的关键字有哪些 ?

this 指向当前函数的上下文对象

arrguments 指向函数调用时传入的所有参数

rest 写在参数列表的最后面,用 ' . . . ' 三个点标识。这个关键词会将所有多余的参数收集为数组,如果参数不够或者刚刚好,就会为空数组

return 返回值

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值