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 返回值