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,跨域,数据结构,算法,事件循环