前端面试题

JS

【1】JS的数据类型和存储上的差别

1、基本数据类型:Number 、String、Boolean、undefined、null、Symbol

     ——再说说每个基本数据类型的一个特点:

Number:Number类型但是返回的不是数值异常错误。Number包括整数、浮点数、可用十进制、  八进制、十六进制表示,八进制零开头,十六进制0x开头,浮点数还可以用科学计数法来表示

String:字符串可以使用双引号、单引号、反引号来表示。字符串一旦创建就不可改变,拼接字符串时,是先销毁后创建

Boolean:有true和false两个值。可以将其他的数值类型转换成布尔类型,接着举例。

Symbol:保证属性的唯一性

undefined:声明一个变量不给值的时候,系统默认给一个undefined值

null:空指针,typeOf(null),返回的是Object

2、引用数据类型

Array、Object、Function、Date、RegExp、Set、Map

Array、Object的方法举例,可以可以适当引申到Object.defineProperty。Function的四种表达方式。

3、基本数据类型和引用数据类型存储方式不同、复制之后改变数据另一个数据变化的不同

【2】JS数据结构

1、栈、堆、数组、字典、队列、链表、散列表、树、图

栈:后进先出。数据到达栈顶再往栈压数据数显上溢出,取数据触底再取会下溢。

队列:先进先出,在大于长度的地方插入数据会上溢出,所有数据取出再取会下溢出。由于阐述数据具有空间不可再用的特点,实际长度大于数据长度,会造成伪上溢。

链表:JS中的原型链基于链表这种数据结构。链表是无顺序的线性数据结构,有链首、链尾、每个存储单元有数据data和next属性,next用来存放下一个节点的数据。

字典:有key、value键值对组成的数据结构,JS中的Object对象就是基于字典实现的。

散列表:又叫哈希表,在所有数据结构中效率比较高的数据结构,具有最优时间复杂度而数组和链表查找数据需要先遍历数据。散列表有一个特定的长度,元素根据键存储在特定位置,而键根据散列函数隐射为一个数字,该数字的区间是0到散列表长度。散列表虽然是效率很高的一种数据结构,但是存在散列冲突的问题,解决办法如开放地址法、分离链法等。主要应用于数据的插入、删除、取用,但不适合查询数据。

【3】DOM操作节点方法:创建节点、获取查询节点、更新节点、添加节点、删除节点
  1. 创建节点:

document.createElement()

document.createTextNode()

document.createDocumentFragment()

document.createAttribute() 

  1. 查询获取节点:

document.querySelector()

document.querySelectorAll

document.getElementById()

document.getElementsByClassName()

document.getElementsByTagName()

document.getElementsByName()

document.documentElement()

document.body()

document.all[0]  //获取页面中所有元素标签节点的对象集合

document.parentnNode()

document.childNodes()

document.firstChild()

document.lastChild()

document.nextSibling()

document.previousSibling()

  1. 更新节点:

document.innerHTML()

document.innerText()

document.textContent()

  1. 添加节点:

document.innerHTML()

document.insertBefore()

document.style.color=...//color等其他属性

document.setAttribute()

  1. 删除节点:

parentNode.removeChild()

【4】BOM是什么?和DOM的区别?有哪些API

1、BOM,browser object model,浏览器对象模型,是独立于内容于与浏览器窗口进行交互的对象,作用是和浏览器 进行一些交互效果,比如浏览器窗口回退、前进、滚动条等。还可以获取一些客户信息,比如浏览器版本信息等。

2、bom是操作浏览器窗口的对象,dom是操作文档页面的对象。

      bom的顶级对象的window,dom的顶级对象是document。

      bom,每个浏览器厂商都有自己的规范,兼容性比较差,dom遵循w3c规范。

3、 window.open(),window.moveBy().window.moveTo(),window.resizeBy(),window.resizeTo(),window.scrollBy(),window.scrollTo(),window.close()。这些得搭配一起用。

4、location、navigator、screen、history。

location获取网址信息对象:

1、protocol——协议

2、hostname——主机名

3、port——端口

4、host——主机名和端口

5、pathname——服务器下的文件地址

6、search——?后面的内容

7、href——地址全部信息

8、hase——#后面的内容

navigator: appName   appVersion   cookieEnabled  flatForm  online  userAgent  language

history:history.go(),history.back(),history.foreward(),history.length() 

screen:screen.availWidth(),screen.availHeight(),

screen.width(),screen.height(),screen.plxelDepth(),screen.colorDepth(()

 【5】“==”和“===”的区别

等于隐式转换之后的比较,全等于在隐身转换前的比较。

隐式转换后的比较被人的直觉误判:比如:

""=="0",false

""==0,true

false==0,true

false=='0',true

false=='false',false

false==null,false

false==undefined,false

null==undefined,true

【6】typeOf和instanceOf区别

1、typeOf返回字符串,instanceOf返回Boolean值

2、typeOf适合判断基本数据类型,因为但是typeOf的基本数据类型null返回的是Object,引用数据类型Function外其他都返回Object,instanceOf判断引用数据类型,无法判断基本数据类型。

一个通用的既可以判断基本数据类型又可以判断引用数据类型的方法:Object.prototype.toString(需要判断的数据)

【7】原型和原型链

原型:有显式原型prototype、隐式原型__proto__,显式原型:prototype,是函数中的一个属性,包含自有属性constructor指向原函数,和__proto__指向原函数的原型对象。

原型链:比方说要在一个对象中寻找一个属性或者方法,自身上没找到,就会沿着__proto__向原型对象上找该属性或方法,层层递进,直到找到该方法或属性或者直到末尾原型对象。

引申:原型、原型链实现js继承。

引申:字面量创建对象和Object.create(object,{})创建对象的区别:

          Object.create()创建对象很纯净,不会继承原型链上的属性或者方法。

【8】作用域、词法作用域、作用域链

作用域:变量和函数生效的区域或集合,或者说是代码块里面的资源的可见性。分为全局作用域、函数作用域、块级作用域。

词法作用域:JavaScript就是遵循的词法作用域,就是代码写好时作用域就形成了。

作用域链:在一个作用域中找某个变量,没找到再到外层作用域找,直到找到这个变量或者直到全局作用域。

【9】this绑定(指向)

this分为运行时绑定编译时绑定

this运行时绑定,每个函数运行时会生成一个this对象,函数不同的调用方式使得this指向不一样。this的运行时绑定分为new绑定、显式绑定、隐式绑定、默认绑定。

  1.  new绑定,一般情况this指向实例对象  ,如果函数return一个{}对象,this指向这个对象
  2. 显式绑定,通过apply() call() bind()三个之一的方法手动调整this指向。
  3. 隐式绑定,作为一个方法传入一个对象中,this一般指向上一级对象那个。如果在执行前函数单拎出来赋给一个变量,再执行,那么this默认指向window对象(非严格模式)或者undefined(严格模式)
  4. 默认绑定,默认情况下,直接调用这个函数,严格模式下this指向window对象,在严格模式下this指向undefined。

this编译时绑定,箭头函数就是编译时绑定,使得在箭头函数中this是指向window对象的。因此避免在绑定事件或者在某对象原型上添加方法——`obj.prototype=...`时使用箭头函数。

绑定方式优先级:new绑定>显式绑定>隐式绑定>默认绑定

【10】apply() call() bind()区别

三者都是传入两个参数,当第一个参数传入null或者undefined的时候,this指向window对象。

不同的是,apply()和call()当传入第一个参数时会立即执行,临时改变this指向,而bind()传入第一个参数时不会立即执行,而是返回一个永久改变this指向的函数。apply()第二个参数用一个数组来接受,而call()和apply()直接接收一个参数列表,如(obj,1,2,3)。二者不同的是,call()参数列表一次性传入,而bind()可以分多次传入。

【11】new关键字

new一个实例对象的过程:

  1. 创建一个新的对象
  2. 将这个新的对象和原函数通过原型链链接起来
  3. 将原函数的this指向这个新对象
  4. 如果return出基本数据类型,忽略,如果return一个对象类型this指向这个对象,默认返回new后新创建的对象,但是认为的在return后面放一个不相关的对象,容易得到undefined。如果没有返回语句,则默认返回新新创建的那个对象。

比如:function person(name){

            this.name=name,

            return {age:17}

} ;

           const p=new person("张三");

           console.log(p)    //{age:17}

           console.log(p.name)   //undefined

【12】执行上下文,执行栈

执行上下文:js抽象概念,js代码执行的地方就有执行上下文。

分为三种执行上下文:全局执行上下文、函数执行上下文、eval执行上下文。

三段生命周期:确认上下文、执行上下文、回收上下文。

确认阶段:this确定、词法环境组件确认、变量环境组件确认。词法环境和变量环境都有四个属性:environment(词法环境或变量环境)EnvironmentRecord(环境记录)、Type(全局环境还是函数环境)outer(是对null的引用还是idui外部函数的引用)。确认阶段,var存储声明且存储初始化值:undefined,const\let存储声明且不初始化。

执行阶段:存储变量,执行代码。

回收阶段:Node.js中VM模块虚拟机回收代码。

执行栈:遵循后进先出原则。

  1. 首先生成一个全局执行上下文压进执行栈中,
  2. 然后每遇到一个函数,生成函数执行上下文,压进执行栈中
  3. 执行位于栈顶的函数执行上下文,后释放,直到栈底全局执行上下文被释放
【13】事件,事件流,事件模型

事件:HTML文档中或浏览器中的交互行为,赋予页面互动功能。

事件流:父节点、子节点都绑定了事件,触发子节点时,执行事件有一个顺序问题,即事件流。

事件模型:原始事件模型、标准事件模型、IE事件模型。

          原始事件模型优点时速度快,缺点是速度可能快过dom挂在速度影响正常执行,然后只有冒泡事件没有捕获事件,最后就是同类型的事件只能绑定一次。

         标准事件模型,分为三个阶段:捕获事件阶段、处于目标阶段、冒泡阶段。同一类事件可以多次绑定而且不会被覆盖掉。添加事件:addEventListener(绑定事件,回调函数,true捕获false冒泡);取消绑定事件:removeEventListener(绑定事件,回调函数,true捕获false冒泡)。

        IE事件模型,attachEvent(事件,回调),包括两个阶段:处于目标事件阶段,冒泡阶段。

【14】事件代理

就是把一个或一组响应事件委托另一个元素上。

应用场景:委托事件。

【15】闭包

什么是闭包?闭包是函数被引用包围,内层函数可以访问外层函数的资源。

闭包的核心?能创建私有变量,延长变量的生命周期。

函数柯里化?避免重复调用相同参数函数,更适合复用。

闭包实现私有变量?js没有实现私有变量的声明,所以可以通过闭包来手动实现私有变量。

【16】浅拷贝、深拷贝

学栈与堆的时候知道了赋值(=)操作基本数据类型时,会在栈中新开辟一个空间存储数据,元数据或新数据发生改变不会影响另一个数据;而用赋值(=)操作引用数据类型的时候,在栈新开辟一个空间存放地址指向堆里同一个数据,无论是改变原变量数据还是改变新变量中的数据都会影响另一个变量数据。

那么浅拷贝,就能解决赋值(=)操作引用数据类型存在的栈与堆存储问题。当然只能解决第一层数据拷贝之后不被某方数据被修改而影响的问题。——即第一层数据是对值的拷贝,第二层或者更深层的数据就是对地址的拷贝了。方法有:

1、Array.concat(...array)    //传入关于n个数据,返回一个新的数组

2、Object.assign({},obj1,obj2......)    //第一个参数是新对象,后面是n个对象,返回新创建的对象

3、拓展运算符:[...array],{...obj}

4、Array.slice()

这个时候就需要深拷贝了。深拷贝就是无论是第几层的数据都是拷贝值而非地址。方法有:

1、lodash的js库:_.cloneDeep()

2、JSON.parse(JSON.Stringfy(...))

3、递归函数自定义一个深拷贝方法

【17】字符串常用方法

增:concat()

删:trim()  trimLeft()    trimRight()   splice()    subString()   subStr()

改:replace()  padStart()   padEnd()   repeat()  toLowerCase()  toUpperCace()

查:indexOf()  charAt()    search()  match()   includes()

转换成数组:split()

【18】数组常用方法

增:push()  unshift() concat()

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

改:replace() splice() 

查:indexOf()  some() every()  find()  

排序:sort() reverse()

遍历:map() forEach() reduce() filter()

【19】函数缓存

跟闭包、柯里化、高阶函数有关。

缓存计算结果,提高效率,节约计算资源。

【20】事件循环、同步任务、异步任务、宏任务、微任务

事件循环:js是一门单线程语言,但不代表时阻塞的,通过事件使其非阻塞。

单线程就是同一时间只有一个任务,多线程就是同一时间执行多个任务。同步任务就是在优先于其他任务在主程中运行的任务,异步任务就是等待主程召唤(调用异步函数)才运行的任务,微任务就是等主程任务结束后执行的任务,宏任务是最开始开启的任务和等微任务结束后开启一个新的宏任务。

属于微任务的函数:

Permise实例.then()

proxy

process.nextTick (node.js)

MutaionObserver

宏任务:

setTimeout() 

setInterval()

setImmediate()     I/O (node.js)

UI事件 /rendering UI 

异步 

你可能感兴趣的:(vue.js,前端,javascript)