js面试题

JS面试题

1.js数据类型

​ 基本类型:保存在栈内存中的,有

​ String,Number,null,undefind,boolean,symbol(防止属性命名污染,实现属性的私有化,使外部无法直接访问,会返回一个唯一的symbol值)

​ 引用类型:保存在堆内存中的,有

​ 对象,数组,函数

2.js有哪些内置对象

​ 数组Array,字符串处理String,Number数字,Date时间,Math数学计算,RegExp正则表达式,Boolean布尔

3.列举js清空数组的方法?

​ 1.直接赋值为空

​ 2.使用数组的splice方法,传入两个参数,第一个是从下标为0开始,第二个是删除的个数,也就是array.length

4.如何来判断一个对象是否是数组?

​ 1.通过Array.isArray()传入验证的对象即可。

​ 2.通过Object.prototype.toString.call()传入验证的对象

​ 3.通过对象.constructor.name 判断返回的值是否等于 “Array”

5.= =与= = =的区别?

​ == 不严格相等,比较值,类型不同的话会进行类型转换,再去对比两个值是否相等。

​ 判断两个值是否相等:

​ 1.当两个值的类型相等的时候直接进行运算,不需要进行自动转换类型

​ 2.当两个值的类型不相等的时候,要先进行自动类型转换,不能直接进行运算

​ 这时,两个变量的值如果相等就会返回true,否则就会返回false。

​ === 严格相等,比较值和类型,只有类型和值相同时才会返回true。不管两个变量的类型是否相等,都不会进行自动转换,只有值和类型相等才会返回true,否则就是返回false。

6.this的指向问题

​ this永远指向最后的调用者

​ 1.全局中的this指向的全局对象

​ 2.普通函数中的this指向的是调用该函数的调用者

​ 3.箭头函数中的this指向外层

​ 4.事件函数中的this指向的是绑定事件的事件源

7.let和var的区别

​ 相同点:都是用来声明变量,并且使用之前必须要进行初始化

​ 不同点:

​ let:

​ 1.相同作用域中不能重复声明

​ 2.用于块级作用域,不存在变量提升,全局声明的时候不会赋值给全局对象

​ var:

​ 1.变量可以重复声明

​ 2.会进行变量提升

​ 3.全局声明不仅声明为全局变量,并且会赋值给全局对象

8.事件循环

​ js是一门单线程的语言,所以会导致代码的阻塞。分为了同步任务和异步任务,首先会等待所有同步任务执行完毕之后才会执行异步任务。异步任务分为宏任务和微任务,微任务执行完之后才会执行宏任务,宏任务的执行时间越短就会越先执行。

9.简述防抖节流

​ 防抖:就是在指定的时间内,频繁的去触发某个事件的时候,它会重新开始计时,直到最后一次触发该事件的时候才会开始计时。一般作用在键盘事件上

​ 节流:在指定的时间内,频繁触发某个时间,它会等待上一个时间结束之后才会重新计时。一般作用在鼠标事件上。

11.改变this的指向

​ bind,call:参数是一个一个传的

​ apply:传的是一个参数数组

​ 区别:

​ call和apply会立即执行,bind不会

​ 应用场景:

​ 防抖节流中修正this指向

12.深浅拷贝

​ 浅拷贝:只拷贝第一层,如果第一层为对象的话,就会拷贝它的地址,修改原来对象的数据,拷贝出来的对象也同样是会受到影响的

​ 深拷贝:不止拷贝一层,会递归进行拷贝,声明出一个新的对象,然后将值一个一个拷贝进去,拷贝出来的是一个新的对象,修改原来对象的数据,拷贝出来的对象是不会受到影响的

​ 实现方式:

​ 深拷贝:

​ 第三方库lodash,通过cloneDeep

​ juqery提供的$.extend

​ 浅拷贝:

​ 直接赋值

​ concat,slice

​ Object.assign

14.模块化

​ CommonJS:同步加载模块,通过module.exports导出模块,require导入模块

​ es6模块化:通过export导出,如果没有加default的话就是按需导出,导入的时候就需要按需导入,名字需要和导出的命名一致。都是通过import来导入的。

​ 应用场景:

​ 一般用于项目中的util,例如导出时间转换函数

15.es6新特性

​ 模板字符串:使用反引号来代替双引号和单引号,支持多行字符串

​ 对象简写:当属性名和属性值同名的话,可以简写成一个

​ 箭头函数:匿名函数,不作为构造函数使用,绑定外层this

​ 解构赋值:将属性或值从对象,数组中取出,赋值给其他变量

​ promise:用于解决函数嵌套函数的问题,也就是回调地狱。会返回成功或者是失败的结果,.then执行的是resolve成功的结果,.catch执行的是reject失败的结果。.then和.catch代码都会异步执行。

​ 展开运算符

​ async、await

​ let和const:

​ let:块级作用域,不会进行变量提升,使用let声明的变量不能出现重复的变量名

​ const:使用const声明变量,它的值是不能够被修改的。

16.正则

​ 捕获组和非捕获组

​ 正则中使用括号括起来的就是一个捕获组,它存放在正则缓冲区内,以便于后期能够被反向引用。

​ 非捕获组的话是没有存放在正则缓冲区中的,后期不用被方向引用,可以通过:?将捕获组转成非捕获组,这样可以提高性能

​ 正则的常用字符

​ \w匹配字母数字下划线

​ \d匹配数字

​ \s匹配任意空格字符

​ \W匹配结果跟\w相反

17.ajax串行和并行

​ 修改ajax中的async属性,属性值为true的话就是并行,false就是串行

18.什么是跨域,如何解决跨域

​ 为了网络安全,浏览器设置同源策略,要求端口,协议,域名都相同才叫同源,只有有一个不同就视为跨域。

​ 前后端都可以解决跨域

​ 服务端设置响应头,cors (方便)

​ 通过nginx反向代理

​ 开发环境中在webpack配置文件中配置devServer

19.mouseover,mouseout,mouseenter,mouseleave

​ mouseover,mouseout:会冒泡

​ mouseenter,mouseleave:不会冒泡

20.dom和jquery的转换

​ jquery转成dom:通过jquery对象.get()或者是jquery对象[下标]

​ dom转换成jquery:通过$(dom对象)

21.谈谈promise

​ 用来解决回调地狱(函数的层层嵌套,代码冗余,页面代码排版很乱)问题,他会返回成功resolve或者是失败reject的结果。newPromise里面的代码会同步执行,.then和.catch里面的代码会异步执行

​ promise封装ajax:

​ 写一个函数,然后在这个函数中返回一个promise,在onload成功执行resolve回调,onerror失败执行reject回调

22.async,await

​ 使用async修饰的函数就是异步代码,函数里面有返回值的话就是返回一个promise。await必须放在async修饰的函数中,会等待请求异步函数中的成功返回结果。如果有多个await的话,就可以使用Promise.all来并发执行。

23.赋值过程

​ 基本类型的赋值过程,数据是保存在栈中的

​ 引用类型的赋值过程,数据是保存在堆中的,保存在栈内存中的只是变量的标识符

24.原型和原型链

​ 原型:每个对象或者是函数都有一个__proto属性,它的值就是一个对象,即原型对象。

​ 原型链:当对象在使用某个属性的时候,首先会在自身内进行查找,查找的到的话就可以直接使用,如果查找不到就会沿着__proto往上找,直到找到Object的原型对象,也就是null。对象属性找不到的话会返回undefind,方法找不到的话就会直接报错。

25.作用域和作用域链

​ 作用域:定义了标识符(变量名,函数名)的有限访问范围

​ 作用域链:函数内部访问函数外部的变量或者是函数的时候,首先会在自身作用域中进行查找,如果查找不到的话就会到父级作用域中查找,直到找到为止,如果找不到就会直接报错。这种链式的查找过程就是作用域链。

26.闭包

​ 闭包就是在父函数中返回子函数,并且子函数中引用到了父函数中声明的变量,就是闭包。

​ 优点:可以延长变量的生命周期;全局中实现访问私有变量

​ 场景:单例模式;防抖节流

27.事件委托以及原理

​ 就是子元素委托父元素来代替执行某些事件,就比如说我现在有一个tabbar,用ul和li实现的,然后要给每个li都绑定一个点击事件,那就会很耗性能,这时候就可以用到事件委托,通过给ul绑定点击事件,在事件对象.target来判断是否是li元素

28.阻止默认行为,阻止冒泡

​ w3c:stopprogation

​ ie:cancelBubble = true

​ w3c:preventDefault

​ ie:returnValue = false

29.数组常用的方法和字符串常用的方法

​ 数组:

​ 1.push添加元素或数组至原数组的尾部

​ 2.concat合并一个或多个数组

​ 3.pop删除数组中的最后一个元素,并且会返回被删除的元素数据

​ 4.reverse 对数组进行反转

​ 5.join 将数组以某个字符进行合并

​ 6.reduce 就是一个累加器,对数据进行累加求和。

​ 字符串:

​ 1.length获取字符串的长度

​ 2.indexOf查找指定符出现的位置

​ 3.lastIndexOf查找指定符最后一次出现的位置

​ 4.split将数组以某个字符来进行炸开,返回一个数组

​ 5.toLowerCase 将字符串转换成小写的形式

​ 6.toUpperCase 将字符串转换成大写的形式

30.dom和bom

​ dom:文档对象模型,用于操作文档api,document就是它的一个对象,因为dom和文档有关,所以它关注的就是网页本身的内容

​ bom:浏览对象模型,用来操作浏览器中的api,可以对浏览器窗口进行访问和操作,window就是它的一个对象

​ location.reload() 刷新页面

​ history.go()为负数的话就是后退,正数的话就是前进

​ 也可以通过history.back()后退

31.dom和jquery的一些操作

​ dom:

​ setAttribute:设置属性

​ getAttribute:获取属性

​ removeAttribute:移除属性

​ createElement:创建元素

​ classList.add添加类

​ jquery:

​ attr:传入一个参数的话就是获取,两个参数的话就是设置

​ aaddClass:添加类

​ prop:也是用来添加属性,就是一般会用在复选框,它可以设置true和false

​ hide和show:元素的显示和隐藏

32.箭头函数和普通函数的区别

​ 1.普通函数可以作为构造函数,可以使用new关键字;箭头函数是匿名函数,不可以作为构造函数,不可以使用new关键字

​ 2.箭头函数中的this指向的是外层,普通函数中的this指向的是调用该函数的调用者

​ 3.箭头函数是没有prototype属性的

​ 4.箭头函数中是没有绑定argument的,普通函数中参数都是放在argument中的。

33.map和filter的区别

​ map用来操作数组中的内容,会返回一个新数组,return的值如果是布尔的话,他返回的数组中数据就是bool值。

​ filter用来过滤数组中的内容,会返回一个新数组,只有return条件为真的时候才会通过,为false的话就是不通过。

34.ajax实现文件上传

​ 通过post请求,表单enctype属性设置为multipart/form-data,ajax请求的时候需要配置processData,contentType都为false,还有就是传递的数据类型要是fromData。

35.事件流

​ 事件捕获,目标阶段,事件冒泡

36.数据结构

​ 分为:队列和栈,队列就是先进先出,栈就是先进后出

37.new的一个过程,如何实现

 1. 先创建一个新的对象
 2. 将对象的__proto__属性放在构造函数的prototype属性上面
 3. 改变构造函数中的this指向(call,apply)
function myNew (fun, ...arg) {
   // 创建一个新对象且将其隐式原型指向构造函数原型
   let obj = {
       __proto__: fun.prototype 
   }
   // 执行构造函数
   fun.apply(obj, arg)
   
   // 返回该对象
   return obj
}

function Person (name, age) {
   this.name = name ;
   this.age = age
}

let _person = myNew(Person, 'huang', '21')
console.log(_person)

38.什么是Vdom?
就是用来描述真实dom的一种技术,通过diff算法,可以精准知道哪些真实dom发生了变化,从而减少了dom的性能开销
分为了三步骤:
1.将真实dom编译成虚拟dom(compile)
2.通过diff算法,比较旧的vdom和新的vdom有什么差异(diff)
3.通过补丁的方式更新到真实dom上面(patch)

数据类型,赋值过程,this,两链一包,模块化,es6新特性,dom和bom,数组,字符串方法,捕获组和非捕获组,jquery,dom和jquery的增删改,ajax,跨域,数据结构,算法,事件循环

你可能感兴趣的:(js,面试)