目录
1、说一说常见的数据类型?
基本数据类型:String、Number、Boolean、Undefined、Null、Symbol、BigInt
引用数据类型:object(array、function、date、math、Reg)
2、var、const和let区别?
var声明的变量为全局作用域、而let声明的变量为块级作用域、const声明的常量为块级作用域。var声明的变量存在变量提升,而const和let不存在变量的提升。var可以重复声明同一个变量、let和const不能声明同一个变量,const声明的值不能修改,但是如果const声明的是一个对象,对象里面的属性和值可以修改.
3、ES6新增的特性
let、const,箭头函数、模板字符串、解构赋值、扩展运算符、set、map、promise对象。
4、如何判断JS数据类型?
typeOf:返回判断数据的类型。对于简单数据类型,除了null返回object,其他都可以正确判断。对于引用数据类型,除了function外都会返回object。
instanceof:判断对象的原型链__proto__上是否存在构造函数的原型prototype,只能判断引用数据类型,不能判断基本数据类型,常用来判断a是否为b的实例。
object.prototype.toString.call():返回类型为[object 数据类型]
5、讲一下闭包?
函数嵌套函数,内部函数就是闭包。内部函数可以访问外部函数中的变量,内部函数没有执行完毕,外部函数中的变量不会被销毁。作用:封装一段代码,避免全局变量污染问题。
6、什么是事件代理?
事件代理也叫事件委托。就是把原本绑在子元素上的点击事件绑定在父元素身上,通过事件冒泡原理父元素可以监听到子元素上的点击事件,触发相应的操作。举例:ul中li标签的事件监听,把原本绑定在li上边的监听事件绑定在ul上,这样的好处是可以实现动态元素的绑定。
7、事件循环?
由于js为单线程,当遇到同步任务和异步任务时,一般把同步任务放在运行栈中,当遇到异步任务的时候会把异步任务放到任务队列中,直到同步任务执行完毕之后再执行异步任务,由于一次只能处理一个异步任务,所以处理完一个异步任务后又会在任务队列中查找下一个任务,以次循环往复直到执行完最后一个任务就称为事件循环。
8、什么是宏任务和微任务?
宏任务:计时器、ajax、dom事件
微任务:promise.then、process.nextTick
9、JS运行机制,代码执行机制?
JS为单线程,一个任务执行完毕才能执行下一个任务。执行顺序为同步程序执行完成后,执行异步程序
(1)同步任务(2)微任务(3)宏任务
10、数组常见的方法:
增:push(末尾)、unshift(开头)、concat(连接两个数组)
删:pop(末尾)、shift(开头)splice(第一个参数为开始位置、第二个参数为删除数量)、slice
查:indexOf()返回要查找元素在数组中的位置,没找到返回-1、includes()返回要查找元素在数组中的位置,找到返回true、找不到返回false、find()返回第一个匹配的元素
reverse、sort、join
11、说一说js的垃圾回收机制
垃圾回收机制简称GC,JS中的内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收,如果不再用到的内存没有得到及时释放,会造成内存泄漏。
内存的生命周期是:内存分配、内存使用、内存回收。全局变量一般不会回收,关闭页面回收,一般情况局部变量的值不再使用了就会自动回收。
12、原型链?
有一个构造函数,通过new实例一个对象,我们在构造函数的prototype身上添加一个方法,如果实例对象想要使用这个方法,就可以通过实例对象.__proto__来访问这个方法,如果找不到,就会在这个对象的原型的原型上进行查找,一层层查找,直到原型链的末尾,就形成了一条原型链。
13、JS中new操作符做了哪些事情?
(1)创建了临时对象/空对象(2)这个对象的原型指向构造函数的prototype(3)this指向这个对象(4)执行构造函数(5)返回临时对象。
14、如何理解JS中的面向对象的?
面向对象是一种编程思想,简称oop
在es5中创建对象的方式:
(1)对象字面量形式:var obj = {}
(2)new Object()构造函数:var Obj = new Object()
(3)构造函数模式
面向对象的三大特征:封装性、继承性、多态性
优势:易于维护、代码可读性高、易扩展
对象遍历:可以用:for...in...
对象转换为字符串:JSON.stringify()、JSON.parse()
设计模式:
单例模式、工厂模式、观察者模式、订阅模式
es6: (1)class类名称
(2)static静态属性
(3)constructor构造函数
(4)super父类构造函数
(5)extends继承关键
15、说一说promise?
promise是es6新增的技术,它是一种异步编程的新的解决方案,它是一个对象,通过new创建,promise有三种状态:pending(初始)、fulfilled或resolve(成功)、rejected(失败),它的状态改变有两种可能:从pending到fulfilled,从pending到rejected,这两种情况只要发生,状态就不会再变了。支持链式调用,可以解决回调地狱问题。api:then、catch、race、all、try。
16、你知道call、bind、apply的区别吗?
区别:(1)三者都可以改变函数的this指向。
(2)apply和call可以会立即执行,而bind会返回一个函数,后续需要的时候再调用执行
(3)call和bind传递参数一次列出的,apply传递的参数是数组。
17、数组去重?
(1)indexOf:循环去重
(2)Set去重:Array.from(new Set(array))或者Array.from(...new Set(array))
let arr1 = [1, 2, 3, 1, 2, 5]
function unique(arr) {
return [...new Set(arr)]
}
console.log(unique(arr1));
(3)includes去重
18、说一说防抖和节流?
防抖:当用户多次触发回调函数时,只触发最后一次操作的,其余的全部忽略掉。
函数节流:是确保函数特定的时间内至多执行一次。
19、ES6新增数组方法?
(1)forEach函数:数组.forEach(function(属性值){相应操作})
let arr = ['red', 'pink', 'blue', 'black']
let newArr = arr.forEach((item) => {
console.log(item); // red pink blue black
})
(2)map方法:一定要有返回值,否则就会返回undefined,返回值是一个数组。
应用场景:返回一个要利用原数组经过运算后的数组,或者在一个对象数组中拿到某个属性,并返回一个新数组的情况。
let arr1 = ['西游记', '红楼梦', '三国演义', '水浒传']
let arr2 = arr1.map(item => {return item})
console.log(arr2); // ['西游记', '红楼梦', '三国演义', '水浒传']
(3)filter可以返回一个新数组,也可以改变原数组。
let carBand = ['奔驰', '宝马', '丰田', '本田', '五菱宏光']
let benChi = carBand.filter((product) => {
return product === '奔驰'
})
console.log(benChi);
(4)find()方法:只会找到第一个符合的,找到之后就会返回,就算下面还有符合要求的,也不会再找下去。
let number = [2, 5, 6, 8, 10, 15, 12, 2]
let even = number.find((item) => {
return item % 2 === 0
})
console.log(even); // 2
(5)some方法:只要有一个满足就行,一真即真
let persons = [
{name: '张三',age: 15},
{name: '李四',age: 25},
{name: '王五',age: 30}
]
let some = persons.some((person) => {
return person.age > 20
})
console.log(some); // true
(6)every方法:要所有的满足才行,一假即假
let persons = [
{name: '张三',age: 15},
{name: '李四',age: 25},
{name: '王五',age: 30}
]
let every = persons.every((person) => {
return person.age < 20
})
console.log(every); //false
(7)reduce()方法:reduce(function(sum,number){...},0),要有两个参数,第一个参数一定要初始化
let numbers = [5, 10, 15]
let res = numbers.reduce((sum, number) => {
console.log(sum);
return sum + number
}, 0)
console.log(res); // 30
20、延迟加载JS有哪些方式?
延迟加载:defer、async
例子:
<script defer type = "text/javascript" src='demo.js'>
defer:所有的html执行完,然后依次执行js代码。
async:与html同步执行。
21、null和undefined的区别?
(1)null会被隐式转换为0,空对象指针;undefined转为数值为NaN
(2)null是个对象、undefined是个undefined类型(typeof判断)
22、slice是干嘛的、splice是否会改变原数组?
(1)slice是来截取的
slice(2)、slice(1,3)、slice(-3)
返回一个新数组
(2)splice:插入、删除、替换
返回删除的元素、该方法会改变原数组
23、JS的继承方式有哪些?
方式一:ES6继承
class Parent {
constructor() {
this.age = 20
}
}
class Children extends Parent {
constructor() {
super();
this.name = '小明'
}
}
let p1 = new Children()
console.log(p1, p1.name, p1.age);
方式二:原型链继承
function Parent() {
this.age = 25
}
function Children() {
this.name = '小明'
}
Children.prototype = new Parent()
let p2 = new Children()
console.log(p2, p2.name, p2.age);
方式三:借用构造函数继承
function Parent() {
this.age = 28
}
function Children() {
Parent.call(this)
this.name = '小明'
}
let p3 = new Children()
console.log(p3, p3.name, p3.age);
方式四:组合式继承
function Parent() {
this.age = 30
}
function Children() {
Parent.call(this)
this.name = '小明'
}
Children.prototype = new Parent()
let p4 = new Children()
console.log(p4, p4.name, p4.age);
24、JS的深浅拷贝?
浅拷贝:只复制引用,没复制真正的值。
let obj1 = {a: 10,b: 20,c: 30}
let obj2 = obj1
obj1.a = 30
console.log(obj1,obj2)
let obj1 = {a: 10,b: 20,c: 30}
let obj3 = Object.assign(obj1)
obj3.b = 100
console.log(obj1, obj3);
深拷贝:是复制真正的值(不可引用)
let obj4 = {a: 1,b: 2}
let obj5 = JSON.parse(JSON.stringify(obj4))
obj5.a = 10
console.log(obj4, obj5);
递归形式:
function copyObj(obj) {
if (Array.isArray(obj)) {
var newObj = []
} else {
var newObj = {}
}
for (var key in obj) {
if (typeof obj[key] == 'object') {
newObj[key] = copyObj(obj[key]);
} else {
newObj[key] = obj[key]
}
}
return newObj;
}
25、localStorage、sessionStorage、cookie的区别?
(1)数据存储有效期:
sessionStorage:浏览器关闭前有效
localStorage :永久存储,除非手动删除
cookie:只在设置过期时间内有效
(2)cookie可以设置过期时间,sessionStorage、localStorage不可以设置过期时间
(3)存储大小的限制
cookie大小不超过4k,sessionStorage、localStorage不超过5M
26、箭头函数和普通函数的区别?
(1)this指向
箭头函数的this只在箭头函数定义时就决定,而且不能修改this指向
箭头函数this指向定义时,外层第一个普通函数的this
(2)箭头函数不能new(不能当做构造函数)
(3)箭头函数没有arguments
(4)箭头函数没有prototype