JS常见面试题

1.js中的简单类型和复杂类型(也就是数据类型)

(1)简单类型:String、Number、Boolen、NAN、Undefined、null
(2)复杂类型:Array、Object、Date、function、RegExp
(3)ES6新增数据类型:Symobl

2.js组成的三部分

(1)EMCscript、DOM、BOM

3.js的内置对象

String、Number、Boolen、Function、Array、Object、Date、Regexp、Math

4.js操作元素节点

(1)创建元素节点:createElement()
(2)修改元素节点:appendchild()
(3)删除元素节点:removeChild()

5.数组去重的几种方式

方法很多,千变万化,不离其宗
(1)双层for循环(最基础)

<script>
        let arr=[1,2,3,4,6,1,2,4,3,3,1]
        for(let i=0;i<arr.length;i++){
            for(let j=i+1;j<arr.length;j++){
                if(arr[i]===arr[j]){
                    arr.splice(j,1);
                    j--;
                }
            }
        }
        console.log(arr);
    </script>

(2)单层for循环配合indexOf()

<script>
        let arr=[1,2,3,4,6,1,2,4,3,3,1];
        let newarr=[];
        for(let i=0;i<arr.length;i++){
            if(newarr.indexOf(arr[i])===-1){
                newarr.push(arr[i])
            }
        }
        console.log(newarr);
</script>

(3)使用 new Array(…new set(数组))

6.数组的常用方法

(1)push()向数组的最后追加元素
(2)unshift()向数组的最前面追加元素
(3)pop()删除数组的最后一个元素
(4)shift()删除数组的第一个元素
(5)splice(n,m,x)n是开始截取的位置,m是截取的数量,x是替换截取的元素
(6)slice(n,m)截取元素从n下标开始截取m下标结束不包含m
(7)toString()转化为字符串
(8)join()参数为字符 ,用字符分割元素
(9)concat()拼接两个数组
(10)reverse()反转数组
(11)indexOf()查找某个元素
(12)sort()排序参数为函数(a,b)=>{a-b/a+b}
(13)includes()验证元素中是否含有某个元素

7.Object常用方法

(1)Object.keys()遍历对象所有的属性名
(2)Object.values()遍历对象所有属性值
(3)Obect.assign()浅拷贝
(4)Object.hasOwnpropety(要检测元素)判断对象中是否含有某元素

8.什么是事件委托作用优点

事件委托:就是自己的事情交给别人做,原理就是冒泡机制,常用ul>li举例,给li添加事件通过冒泡机制作用到整个ul上。
优点:提高性能减少事件绑定

9.说说你对闭包的理解

闭包:两句话都是一个意思
(1)一个函数可以访问另一个函数的作用域导致作用域内的数据无法释放。
(2)内层函数有权访问外层函数的作用域
优点:可以保护变量不被污染,可以有权访问一个函数的内部变量
缺点:因为作用域一直被访问导致变量被一直使用无法被js中的垃圾机制(如果你知道什么是垃圾机制就不要说,就说内存无法释放)回收释放,导致内存占用

10.js中的垃圾回收机制

不再使用的变量即生命周期结束的变量会被释放,只能是局部变量,全局变量的生命周期,直到浏览器卸载页面才会结束。

11.谈谈你对防抖节流的理解

防抖:基本用于输入框输入内容场景,事件触发n秒后再执行,如果在n秒内事件被再次输出那么将从新计时,也就是减少时间触发次数
节流:为了防止事件短时间内被多次触发,导致响应的速度小于触发的速度,造成的延迟,假死、卡顿现象

12.判断元素的类型

(1)instaceof
(2)适用数组 Array.isArray

13.js实现继承的方法

(1)原型链继承
优点:写法方便,容易理解
缺点:对象实例共享所有继承的属性和方法,无法向父类构造函数传参
(2)利用构造函数继承
原理:在子类构造函数的内部调用父类型构造函数,使用apply()或者call()
优点:解决了圆形类实现结构不能传参的问题和父类原型共享的问题。
缺点:无法实现函数的复用,子类的所有乐行必须使用构造函数模式。
(3)组合式继承(前两种方法结合)
优点:解决了原型链继承和借用构造函数继承造成的影响。
缺点:无论什么情况下都会调动两次父类构造函数
(4)ES6class关键字extends
最优解,但是兼容问题(IE)
原理:创造出父类的this对象然后子类构造函数修改this,子类的构造方法中必须调用super()方法之后才能使用this,因为之类的this对象时继承父类的this对象然后对其进行加工,而super方法便是的父类的构造函数

<script>
        class father{
            constructor(name){
                this.name=name
            }
            getname(){
                return this.name
            }
        }
        //子类继承
        class son extends father{
            constructor(names){
                super('我是传给父类的参数')
                this.names=names
            }
            getson(){
                console.log(this.names+':'+super.getname());
            }
        }
        const son1=new son('mmm')
        son1.getson()//mmm:我是传给父类的参数
    </script>

14.js中this指向问题

(1)普通函数:this==》window
(2)定时器:this==》window
(3)构造对象:this==》Object
(5)事件处理中:this===》谁触发事件指向谁

15.修改this指向的方法

(1)apply()
参数:第一个参数时要指向的对象,第二个参数时数组用来传递参数
apply(‘新的对象’,[1,2,34,4])
(2)call()
参数:第一个参数时要指向的对象,门后面传递的都时数据
call(‘新的对象’.agr1.agr2.agr3)
(3)bind()
参数:第一个参数要指向的对象,后面也是数据,但是这个函数需要调用一下才会执行
bind(‘新的对象’,agr1.agr2)()这里时函数自导用的写法

16.如何将一个对象转化为JSON,如果再转化回来?

(1)JSON.stringify()
(2)JSON.parse()

17.数据解构

…三个点就是解构
let obj={name:‘ddd’}
const {name}=obj

18.var、let、const区别

(1)var 全部变量声明,存在变量提升可以重复声明
(2)let 块级作用域不存在变量提升不可以重复声明
(3)const 是声名常量,必须有初始值,不存在变量提升不可以重复声明

19.深浅拷贝

(1)浅拷贝:浅拷贝是拷贝的地址,当拷贝的对象或者原对象改变了两者都会改变。
最常用的方法Object.assign(新的对象名,要拷贝的对象)
或者用解构也就是扩展运算符也就是…
const obj={…拷贝对象}
(2)深拷贝:
创建一个新对象,将原始对象从内存中完整的拷贝出来,从堆内存中开辟出一个新的区域存放新对象,且修改新对象,不会影响原始对象
const obj1=JSON.parse(JSON.stringify(要拷贝的对象))缺点不能处理函数和正则
手写递归方法

function deepClone(obj, hash = new WeakMap()) {
    if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
    if (obj instanceof Date) return new Date(obj);
    if (obj instanceof RegExp) return new RegExp(obj);
    // 可能是对象或者普通的值  如果是函数的话是不需要深拷贝
    if (typeof obj !== "object") return obj;
    // 是对象的话就要进行深拷贝
    if (hash.get(obj)) return hash.get(obj);
    let cloneObj = new obj.constructor();
    // 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
    hash.set(obj, cloneObj);
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        // 实现一个递归拷贝
        cloneObj[key] = deepClone(obj[key], hash);
      }
    }
    return cloneObj;
}
const obj1 = {
    a: 1,
    b: [1, 2],
}
obj1.c = obj1
const obj2 = deepClone(obj1)
obj2.a = 2
obj2.b.push(3)
console.log(obj1)
console.log(obj2)

当然这个深拷贝也是比较基础的,不能处理 Map、Set以及更加复杂的数据,你能说出来这么多已经是满分了,这里用了递归,面试官可能问你递归的原理和使用方法

20.你对递归怎么理解

递归:自己调用自己(一个函数内可以调用函数本身),需要一个条件让自己停止调用自己,也就是推出条件 return结束
场景:阶乘,累加

21.浏览器的储存方式

(1)cookies
H5之前的本地储存方式兼容性号请求头自带cookie,缺点:存储小为4KB,资源量非使用麻烦(需要自己封装)
(2)sessionStore
当前页面储存,关闭页面后就会立刻清理,不能再所有的同源窗口共享,会话级存储
(3)localStorage
本地存储以键值对的形式存储,操作方便永久储存兼容性好,缺点:有些浏览器会限制储存的类型,有些浏览器再隐私模式下不可读取不能被爬虫

22.说说你对token的理解和使用

token:这是一个相当于身份令牌,一般就是用户通过账号密码登录以后,服务器把这些凭证通过加密一系列操作后生成的一个字符串
存放再localstorage(一般都放在这,但是这需要做个好xss防御)这个尽量别去说xss,不然就是给自己找坑
存放再cookie中会有csrf攻击,会自动发送,但是不能跨域

23.说说你怎么处理跨域

方法千万种,自己会什么说什么
(1)JSONP
(2)后端设置cors()
(3)修改请求头
header(‘Access-Control-Allow-Origin:*’);//允许所有来源访问
header(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式  
(4)在vue中使用http-proxy-middleware

总结:这里就是常问的js面试题,还有promise、async/await异步和ajax、axios、请求方法我会但写一个文章记录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值