前端JS面试重点

前端JS面试重点



一、js的数据类型

1.基础数据类型

Number Boolean String Undefined Null

2.引用数据类型

Object Date Array Function

  • 强制转换数据类型的方法
    1.toString()
    2.Number()
    3.Boolean()
  • 基础数据类型和引用数据类型有什么不同?
    1.存放的位置不同
    基础数据类型存放在栈区,引用数据类型存放在堆区,然而在栈内存中保存了堆内存中引用类型的地址

二、什么是闭包

1.闭包就是可以读取其他函数内部变量的函数

2.闭包就是一个函数内部嵌套一个函数

  • 优点:

1.可以读取其他函数内部的变量

2.避免了全局污染

  • 缺点:

1.变量不会被回收

2.会造成内存泄漏问题

  • 闭包为什么会产生内存泄漏
    原因:因为闭包可以读取函数内部变量,然后这些变量会一直存放在内存中。使用结束没有局部清理,就会产生内存泄漏

三、什么情况下会产生内存泄漏,如何解决内存泄漏问题

  • 产生内存泄漏
    1.未声明的变量
    2.闭包引起的内存泄漏
    3.遗忘掉的定时器或回调
    4.没有清理的DOM元素
    5.全局变量造成泄漏
  • 解决方法
    1.避免创建全局变量
    2.闭包使用结束后,解除闭包
    3.手动清理定时器和DOM
    4.手动删除DOM(elements.btn = null)
    5.关闭页面的时候手动清理

四、 == 和 === 的区别

1.== 是非严格意义上的相等,比较值相等就相等

2.=== 是严格意义上的相等,比较值和数据类型全部相等才相等

五、js的遍历方法有哪些

链接:link
1.for

2.forEach

3.for in

4.for of

5.map

6.some

7.every

8.filter

六、map和forEach的区别

  • forEach()方法不会返回执行结果,而是undefined。也就是说,forEach()会修改原来的数组。
  • map()方法会得到一个新的数组并返回。

七、同源策略

同源指的是域名 协议 端口号相同

八、如何解决跨域

1.JSONP

2.CORS

3.PROXY代理

九、es6的新增特性

链接link
1.新增了let 和 const 的声明变量

2.箭头函数

3.模板字符串

4.函数参数的默认值

5.扩展运算符 Spread /Rest

6.解构赋值

7.for…of和fo…in

8.class类

9.提出promise解决回调地狱

十、let const 和var 的区别

链接link
1.var可以变量提升;let和const不能变量提升

2.var属于全局作用域;let和const是块级作用域

3.var可以多次声明;let和const在统一作用域不可以多次声明

4.var和let可以修改生命的变量;const只能通过方法进行修改,直接修改会报错

十一、箭头函数与普通函数的区别

链接link
1.箭头函数带箭头

2.箭头函数属于匿名函数

3.箭头函数不能用于构造函数,不能使用new

4.箭头函数this指向父级,普通函数this指向全局或者调用它的对象

5.call() bind() apply()无法改变箭头函数的this指向

十二、什么是async和await/他们有哪些作用

链接:link

  • async和await属于promise的语法糖,asnyc作为一个关键字放在函数前面,表示该函数是一个异步函数,意味着该函数执行时不会堵塞后边代码。它返回的是一个promise对象。
  • await用于接收promise对象,他只能在异步函数中使用,否则会报错。

十三、常用的数组有哪些方法

1.isArrary()判断参数是不是数组;返回布尔值
2.toString()将数组转换成字符串
3.push()在数组末尾添加元素
4.unshift()在数组开头添加元素
5.pop()删除数组末尾的值,并返回删除的值
6.shift()删除数组开头的值,并返回删除的值
7.reverse()翻转数组
8.join(‘符号’)拼接字符并且以‘符号’隔开
9.sort()排序
10.concat 拼接数组
11.slice()

  • slice(开始索引值,结束索引值) 数组截取(下标)包括左边不包括右边
  • 如果第二个数是正数, 返回从开始位置到结束的位置(但不包括最后结束的位置)
  • 如果第二个数是负数,返回的是开始位置到结束位置减一
  • 如果第二个数是0或者两个数都是负数,则返回[]
var nums = [1,2,3,4,5,6,7,8,9]
console.log(nums.slice(0,4))//1,2,3,4   
console.log(nums.slice(2))//3,4,5,6,7,8,9
console.log(nums.slice(2,nums.indexOf(6)))//3,4,5
console.log(nums.slice(2,0))//[]
console.log(nums.slice(2,-1))//3,4,5,6,7,8
console.log(nums.slice(2,-2))//3,4,5,6,7

12.indexOf和lastIndexOf

  • 数组名.indexOf():某个元素从左到右第一次出现的下标
  • 数组名.lastIndexOf:某个元素从左到右最后一次出现的下标
var nums = [1,5,1,16,56,6,5,66]
var index = nums.indexOf(5)
console.log(index)//1

index = nums.lastIndexOf(5)
console.log(index)//6

13.filter()过滤
过滤后形成新的数组
不会影响原数组

  • 筛选单个值
var money = [1500, 1200, 2000, 2100, 1800]
var arrs = money.filter(function(v) {
	//输出数组里小于2000的元素
    return v <= 2000
})
console.log(arrs.toString())//1500,1200,1800

  • 筛选对象
//筛选出工资大于4000的员工信息
var people = [
    {name:'赵俊',age:18,salary:8000},
    {name:'张三',age:18,salary:4000},
    {name:'李四',age:18,salary:6000},
    {name:'王麻子',age:18,salary:3000},
    {name:'刘辰',age:18,salary:2200}
]
var arrs = people.filter(function(v){
    if(v.age >= 18)
        return v.salary >= 4000
})
console.log(arrs)//Array(3)

14.find()和findIndex()

  • 数组名.find():查找数组中满足条件的第一个元素,返回该元素,没找到输出undefinded
  • 数组名.findIndex():查找数组中满足条件的第一个元素,返回该元素下标,没找到输出-1
//find------找到是否存在值,找到输出查询的元素,没找到输出undefinded
var nums = [15,56,44,2,36]
var a = nums.find(function(v){
    return v == 15
})
console.log(a)//0
//findIndex------找到是否存在值的下标,找到输出元素的下标,没找到输出-1
a = nums.findIndex(function(v){
    return v == 15
})
console.log('下标是:'+a)//下标是:0

15.map()
返回一个新的数组

var salary = [1500,1200,2000,2100,1800]
//给每个员工涨工资1000
var arrs = salary.map(function(v){
    return v*2
})
console.log(salary.toString())//1500 1200 2100 1800
console.log(arrs.toString()) //3000 2400 4000 3600

16.every和some

  • 数组名.every()—全部满足条件 全部都满足则返回true,否则返回false 相当于&&
  • 数组名.some()—只要有一个满足就返回true 全部都不满足则返回false 相当于||
var people = [	{name: '赵俊',age: 18,year: 1,salary: 8000},
				{name: '张三',age: 18,year: 2,salary: 4000},
				{name: '李四',age: 18,year: 3,salary: 6000},
				{name: '王麻子',age: 18,year: 4,salary: 3000},
				{name: '刘辰',age: 18,year: 6,salary: 2200}
			]
			
                //every()---全部都  全部都满足则返回true,否则返回false
                var a = people.every(function(v){
                    return v.salary >2000
                })
                if(a){
                    console.log('公司所有人工资都大于2000')//公司所有人工资都大于2000
                }else{
                    console.log('公司有人工资小于2000')
                }
                //some()---只要有一个满足就返回true  全部都不满足则返回false
                a = people.some(function(v){
                    return v.age <18
                })
                if(a){
                    console.log('公司有人未满十八')
                }else{
                    console.log('公司所有人都是十八岁及以上')//公司所有人都是十八岁及以上
                }

17.reduce()

  • 求和
var nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
			var sum = nums.reduce(function(tatol, v) {
				return tatol + v
			},0)
			console.log(sum) //45

  • 二维数组转一维数组
nums[
    [1,2,3],
    [4,5,6],
    [7,8,9]
]
var arrs = nums.reduce(function(nums2,i){
    return nums2.concat(i)
},[])
console.log(arrs.toString())// [1,2,3,4,5,6,7,8,9]

  • 统计一个数组中有多少个不重复的单词
var arr = ["apple","orange","apple","orange","pear","orange"];
 
function getWordCnt(){
  return arr.reduce(function(prev,next){
    prev[next] = (prev[next] + 1) || 1;
    return prev;
  },{});
}

18.splice(start,number,value…): 返回删除元素组成的数组,value 为插入项,改变原数组

十四、this指向问题

1.全局作用域中
this指向window
2.普通函数
谁调用我this就指向谁

 var obj = {
            fn1:function() {
                console.log(this); 
            },
            fn2:function(){
                fn3() 
            }
        }
        function fn3() {
            console.log(this); 
        }
        fn3();//this->window
        obj.fn1();//this->obj
        obj.fn2();//this->window

3.箭头函数
this是上下文中定义的this

 var div = document.querySelector('div'); 
    var o={
        a:function(){
            var arr=[1];
          //就是定义所在对象中的this
          //这里的this—>o
            arr.forEach(item=>{
              //所以this -> o
                console.log(this);
            })
        },
      //这里的this指向window o是定义在window中的对象
        b:()=>{
            console.log(this);
        },
        c:function() {
            console.log(this);
        }
    }
    div.addEventListener('click',item=>{
        console.log(this);//this->window 这里的this就是定义上文window环境中的this
    });
    o.a(); //this->o
    o.b();//this->window
    o.c();//this->o 普通函数谁调用就指向谁

4.事件绑定中的this

  • 事件源.onclik = function(){ } //this -> 事件源

  • 事件源.addEventListener(function(){ }) //this->事件源

var div = document.querySelector('div'); 
    div.addEventListener('click',function() {
        console.log(this); //this->div
    });
    
    div.onclick = function() {
    console.log(this) //this->div
    }

5.定时器中的this

  • 定时器中的this->window,因为定时器中采用回调函数作为处理函数,而回调函数的this->window
    6.构造函数中的this
  • 构造函数配合new使用, 而new关键字会将构造函数中的this指向实例化对象,所以构造函数中的this->实例化对象

十五、JavaScript 深浅拷贝

  • 浅拷贝
    直接赋值
    Object.assign
  • 深拷贝
    1.可以通过 JSON.parse(JSON.stringify(object)) 来解决
    2.第三方库lodash通过 _.cloneDeep(a)来解决
  • JSON.parse(JSON.stringify(object))的缺点
    1.这种方法不能用在函数、undefined、循环引用中
  • 深拷贝和浅拷贝的区别
    1.深拷贝和浅拷贝只支持引用类型
    2.浅拷贝只复制对象的指针而不是本身,新旧对象会共享一个内存,新旧对象会相互影响
    3.深拷贝会创造一个一摸一样的对象,新旧对象不会共享内存,不会相互影响

十六、防抖节流

链接:link

  • 什么是防抖节流
    1.防抖: 在 n 秒内被重复触发,则重新计时,在结束后生效
    2.节流: 在 n 秒内重复触发,只有一次生效

  • 相同点
    1.都可以使用setTimeout来实现
    2.降低回调执行频率,节省计算资源

  • 不同点
    1.防抖:在连续操作结束后,执行一次;节流:一段时间内执行一次

  • 应用场景
    防抖:
    1.搜索框搜索输入。只需用户最后一次输入完,再发送请求
    2.手机号、邮箱验证输入检测
    节流:
    1.滚动加载,加载更多或滚到底部监听
    2.搜索框,搜索联想功能

十七、js的垃圾回收机制

  • 什么是垃圾回收机制
    垃圾回收机制是为了防止内存泄漏,内存泄漏是指当已经不需要某块内存时,该内存还存在;垃圾回收机制就是不定时地寻找不再使用的变量并释放内存。
  • 垃圾回收方法
  • 1.标记清除
    当在函数声明变量的时候,垃圾回收器将其标记为“进入环境”,当函数执行结束的时候,垃圾回收器将其标记为“离开环境”;
    垃圾回收器会将所有变量标记,将不需要的变量进行回收。
  • 2.引用计数
    跟踪一个值的引用次数,当声明一个变量并将一个引用类型赋值给这个变量的时候引用计数+1;

十九、什么是原型 原型链 和继承

链接:link

  • 原型:
    每一个构造函数都会有一个prototype属性,这个属性会在生成实例的时候,成为实例对象的原型对象,js的每一个对象都继承另一个对象,而另一个对象就是原型。除了null之外所有对象都有原型对象。
  • 原型链:
    每个对象都可以有一个原型,这个原型还可以有它自己的原型,以此类推,形成一个原型链
  • 继承
    继承是指一个对象直接使用另外一个对象的属性和方法

二十、什么是作用域和作用域链

  • 作用域:
    作用域指的是一个变量和函数的作用范围。
    作用域分为:可分为全局作用域和局部作用域
  • 作用域链:
    当查找变量的时候,会先从当前作用域的变量对象中查找,如果没有找到,就会从父级作用域(上层环境)的变量对象中查找,一直找到全局作用域的变量对象,也就是全局对象。这样由多个作用域的变量对象构成的链表就叫做作用域链。
var a = 20;
function test() {
    var b = a + 10;//当前作用域没有a,往上找,找到a = 20;
    function innerTest() {
        var c = 10;
        return b + c;//当前作用域没有b,往上找,找到b = a+10;
    }
    console.log(d);//Uncaught ReferenceError: d is not defined,一直往上找,最终也没找到d,所以报错
    return innerTest();
}
test();//40

二十一、js的运行机制

  • js是一个单线程的执行机制;所有任务可以分为“同步任务”和“异步任务”;
  • 同步任务指的是在主线程上排队执行的任务,只有上一个任务自行完毕才能进入下一个任务;
  • 异步任务指的是,不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,异步任务可以执行了,才能进入主线程进行排队。

二十二、说一下宏任务和微任务?

链接:link
宏任务:定时器和用户交互事件
微任务:promise
在js中分为同步任务和异步任务,异步任务分为宏任务和微任务。在代码执行时,先执行同步任务,后执行异步任务。
在异步任务执行时,先执行微任务后执行宏任务。

二十三、什么是promise/promise有哪些方法

链接:link

  • 什么是promise
    1.promise可以解决异步回调地狱
    2.它有两种参数resolve和reject;异步调用成功时用resolve,反之用reject
    3.有三种状态,pending(进行中)、fulfilled(已成功)、rejected(已失败);且状态不可逆

  • promise的方法
    1.promise.all
    只有所有promise成功了,才会执行resolve,并返回成功的值,状态为成功
    只有一个promise失败了,会执行reject,返回失败的值,状态为失败
    有多个promise失败了,会执行reject,返回第一个失败的值
    2.promise.race
    谁第一个完成就返回谁的结果,如果第一个是失败这个 Promise 就失败,如果第一个是成功就是成功;

  • promise.all

  • promise.race

  • promise.any

  • promise.allSettled

二十四、http和https的区别

链接:link

  • HTTP
    HTTP是超文本传输协议,是客户端和服务器之间的通信的响应协议,它用于客户端和服务端之间的请求
  • HTTPS
    由于HTTP协议传输数据都是未加密的,对于隐私信息非常不安全,HTTPS通过HTTP+SSL协议对传输的数据进行加密,增加安全性
  • 区别
    1.HTTPS需要申请证书,一般需要费用
    2.HTTPS是通过SSL协议进行加密处理的,安全性高;HTTP协议是超文本传输协议,是明文的,安全性不高
    3.HTTPS和HTTP使用不同的链接方式,端口也不同,HTTP是80;HTTPS是443

二十五、null和 undefined的区别

  • undefined:
    1.表示一个变量没有被声明,或者声明了没有被覆值
    2.类型是undefined
    3.默认转成NAN
  • null:
    1.表示什么都没有
    2.类型为Object
    3.默认转成0

二十六、事件代理和事件冒泡

  • 事件代理
    事件代理是把原本需要绑定在子元素的响应事件委托给父元素,让父元素担当事件监听的职务。
  • 事件冒泡
    在一个层层嵌套的HTML元素中,最里面的元素触发了某个事件,之后会从里到外相继触发这个事件,这叫做事件冒泡。
  • 如何阻止事件冒泡
    1.阻止事件冒泡可以在调用函数的时候传入event对象,然后在函数里调用event对象的stopPropagation方法。
    2.如果是Vue的话,直接在绑定事件的时候事件名后面加上个.stop就可以阻止事件冒泡了。(.stop事件修饰符)

二十七、图片懒加载和预加载

链接:link

  • 图片懒加载
    对于图片过多的页面,为了加快页面加载速度,需要将页面未出现的区域图片不进行加载,但它出现在可视区域内时,在进行加载;减轻了服务器的压力
  • 实现原理
    懒加载的原理首先将页面上的图片的 src 属性设为空字符串,而图片的真实路径则设置在data属性中,当页面滚动的时候需要去监听scroll事件,在scroll事件的回调中,判断我们的懒加载的图片是否进入可视区域,如果图片在可视区内将图片的 src 属性设置为data的值,这样就可以实现延迟加载。
  • 图片预加载
    提前加载所有图片,当用户需要查看图片时直接从缓存中获取;加强了服务器的压力

二十八、get/post区别

1.get用来获取数据;post用来提交数据
2.get参数有长度限制
3.get和post在本质上都是tcp链接,最大的区别在于get请求时发送一个数据包,而post会产生两个数据包,会先发送header,服务器返回100后在发送data,服务器返回200
4.get传送数据量较小,不能大于2KB;post传送量较大
5.get安全性低;post安全性高
6.get服务器端用Request.QueryString获取变量值;post用Request.From获取提交的数据

二十九、后台如何鉴别权限

  • 当用户填完账号和密码进行验证的时候,服务端会返回一个token值,将token来存放在cookie中,通过router.beforEach(路由拦截)来判断是否登陆成功,根据token值拉取user_info中的用户信息,通过用户信息来算出该用户的权限,通过权限用Router.addRoutes来挂载路由。

三十、什么是回调地狱/如何解决

  • 回调函数嵌套回调函数就叫做回调地狱
  • 通过es6新增属性Promise解决回调地狱问题

三十一、js中的继承有哪些

链接:link

  • 原型链继承
  • es6继承
  • 构造函数继承
  • 实例继承
  • 组合式继承

总结

祝我早日找到管饭的公司

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

样高爸爸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值