程序猿之---Js面试题

74 阅读9分钟

一、常考知识点:

1 ,深拷贝和浅拷贝

Js的两大数据类型有基本数据类型和引用数据类型,基本类型存储在栈内存中,引用数据类型数据存储在堆内存中,栈内存中存放的是引用地址。

(1)     深拷贝会拷贝所有的属性,会在内存中开辟一块新的内存空间,拷贝后修改值互不影响。常用的方法:JSON.parse,JSON.stringfly,lodash-cloneDeep,递归

(2)     浅拷贝如果属性是基本类型的数据,拷贝的就是基本类型数据的值,修改值互相不影响。如果拷贝的属性是引用类型的数据,拷贝的是引用地址,比如修改A对象,那么B对象的属性值也会发生改变。常用的方法有:object.assing() 扩展运算符等

 

2 ,js类型的转换

(1)     显示转换:number string Boolean

(2)     隐式转换:四则运算,判断语句,json方法,三元运算

 

3 ,继承

(1)     ES5继承:原型链,组合式,寄生式继承

(2)     ES6继承:通过extends

 

4 ,作用域

在ES6之前有全局作用域和函数作用域,在ES6之后新增了块级作用域。

在js中作用域是指程序源代码中定义变量(对象、函数)的可访问范围,作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限

(1)全局作用域

作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件

(2)函数作用域

作用于函数内的代码环境,就是局部作用域

(3)块级作用域(let  const声明的遍历具有块级作用域)

在 if 语句、循环语句中创建的变量,仅仅只能在本 if 语句、本循环语句中使用,块作用域由 { } 包括

全局变量和局部变量的区别****

  • 全局变量:在任何一个地方都可以使用,只有在浏览器关闭时才会被销毁,因此比较占内存
  • 局部变量:只在函数内部使用,当其所在的代码块被执行时,会被初始化;当代码块运行结束后,就会被销毁,因此更节省内存空间

作用域链

在当前的作用域中无法获取某个变量时,会在外层嵌套的作用域中去查找,找到最外层的全局作用域中的变量,直到找到改变量。如果在全局作用域没有找到会报错,而这一层一层嵌套起来的作用域就形成了作用域链。

 

5 ,箭头函数

(1)箭头函数是ES6新增的函数,他最大的特点就是没有自己的this,他的this一搬指向书写位置的父级作用域中的this

(2)改变this的指向可以 使用:bind, apply , call, 一般用的最多是bind, bind修改this的指向并且返回的是修改this指向后的函数。

(3)为什么要修改this的指向?因为箭头函数的this指向不是我们当前所需要的,箭头函数作为回调函数它的this不小心指向window可以用改变this指向的方法强制修改成我们需要的。

(4)应用场景:比如在点击事件中有个定时器,定时器不用箭头函数的话,this会指向window。

 

6 ,数组的方法之

forEach() 无返回值,3个参数: 数组元素,数组元素索引,当前的数组

map()

flter() 筛选数组,返回新数组

some() 查找数组中是否有满足条件的元素,只要查找到一个满足条件的就会终止循环,返回布尔值

 

7 ,字符串的方法

trim() 去除字符串两端的空格

 

8 ,filter和some的区别

Fliter是查找满足条件的元素,返回一个数组,把满足条件的全部返回

Some也是查找满足条件的元素,返回布尔值,查找到第一个满足条件就会返回,并且终止循环

 

9 ,some和forEach的区别

Some遇到return为trun时就会终止遍历,迭代效率高,可以查到数组唯一元素

forEach里面return不会终止遍历,会把所有元素都遍历一遍

10,闭包,优点,缺点,什么情况下产生闭包

闭包:一个函数的作用域可以访问另外一个函数作用域里面的局部变量就是闭包。

优点:它的好处可以延伸这个变量的使用范围,创建私有变量,防止全局变量被污染。

缺点:它会造成内存泄漏,因为函数执行完成后,不能将变量进行销毁。

产生闭包的原因:

 

11 ,原型,原型链

原型:

原型链:当我们访问对象上的某一个属性的时候,它会先在自身上去访问,如果自身没有会访问构造函数的prototype指向的实例对象,然后还没找到就利用实例对象的__proto__属性向上查找直到object的prototype,object实例对象也有__proto__属性再向上找直到null。这样一层一层查找就是原型链了。

 

12 ,new之后做的四件事

(1)     创建一个空对象

(2)     让函数的this指向这个空对象,执行构造函数的代码为这个新对象添加属性方法

(3)     设置原型,将对象的原型设置为构造函数的prototype

(4)     返回这个新对象

 

13 ,EventLoop事件循环

Js是单线程的,为了防止一个函数执行时间过长阻塞后面的代码所以会将同步代码放入执行栈,异步代码放入异步队列,异步任务又分为微任务和宏任务,宏任务队列执行的时间比较长,所以微任务优先于宏任务执行,微任务有promise.then,浏览器的mutationObserver。宏任务有settimout,setinterval

 

14 ,防抖

多次触发事件,在规定的时间内频繁触发该事件则重新计时,以最后一次为准。

应用场景:搜索框输入搜索内容

15 ,节流

频繁触发事件后,在规定的时间内函数只能被调用一次,且是最先被调用的那一次。

应用场景:上拉滚动加载更多,表单重复提交

 

16 ,js数据类型  及 检测数据类型的方法

基本数据类型有: String   Number  Null  Undefined  Boolen  Symbol

复杂数据类型有: Object   Array   Function

他们存储的位置不同:简单类型的值存放在栈中,引用类型对应的值存储在堆中,在栈中存放的是指向堆内存的地址

检测数据类型的方法有:

typeof 能判断简单数据类型和函数,不能对null,对象,数组进行精确的判断,返回的都是object

instancof 检测对象之间的关联。可以检测出构造函数的prototype属性在某个实例对象的原型链上,返回布尔值 

Array.isArray 判断传进来的值是否为数组  返回布尔值

Object。prototype.toString.call() 优点可以做到精确判断,如果自身的toString被重写就会在原型上去找。任何类型都能检测出来,缺点 低版本的IE浏览器下  无法兼容

 

17 ,map 和 forEach的区别

共同点:

(1)都循环数组中的每一项

(2)每次循环执行callback函数 的三个参数  数组当前项的值(item) ,数组当前项的索引(index),数组对象本身(arr)

(3)匿名函数中的this 指向window

(4)只能循环数组

 区别:

(1)forEach 返回值undefined,改变原数组

(2)map  有返回值,返回新的数组,原数组不变

(3)map 返回的是数组可以链式操作,forEach 不能。map可以使用return,forEach 里用return 不起作用。forEach 不能用break,会报错,可以利用 try catch 的抛出异常行为来巧妙的停止forEach遍历  

 

18 ,NaN === NaN吗

NaN  和任何 类型都不相等 甚至是它自己本身。因为NaN  表示一个非数字的数值类型,这个非数字类型也是不同的,因此NaN 不等于NaN 。

 

19 ,数组去重 的方法

(1)利用双重for循环,第一层遍历所有数据,第二层循环从第一层循环的下标开始,向后循环,遇到重复的选项,则直接用splice删除相应的选项,最终返回去重后的数组。

(2)利用ES6的 set方法去重,定义一个方法把数组数据传进去new set(arr)这时它返回的是一个对象,利用ES6 的 Array.from或者扩展运算符 转为真数组,然后返回

(3)利用sort 排序方式先去排序然后for循环数组,if判断当前的arr[i] 等于当前的元素让它-1 ,定义一个空数组,把符合的元素push进这个空数组里面并且return

 

20 ,less和sass  的区别

sacc和less 是css预处理器。css 预处理器是一种语言,用来为css增加一些编程的特性,无需考虑浏览器兼容性问题。例如你可以在css中使用变量,简单的程序逻辑,函数等在编程语言中的一些基本技巧,可以让你的css 更简洁,适应性更强,代码更直观等好处。

(1)sass是以$ 开头定义的变量,less 是以@ 开头定义的变量。

(2)sass没有局部变量,满足就近原则。less中大括号内定义的变量为局部变量,作用域和其他程序语言中的作用域非常相同,他首先会查找局部定义的变量,如果没有找到,就会一级一级往下查找,直到根为止

(3)Sass支持条件语句,如if…else、for循环等,而Less不支持。

(4)插值语法不同,Less中使用@{key},Sass中使用#{$key}。

 

21 ,数字怎么取整 的方法

1, Number()

2,parseInt()

3,四舍五入Math.round

4,向上取整Math.ceil

5,向下取整Math.floor

二、内存相关

导语:

内存泄漏写任何语言都必须得注意的问题!!!

1,什么是内存泄漏?

内存泄漏可以定义为程序不再使用或不需要的一块内存,由于某种原因没有被释放,仍被占用。在代码中创建对象和变量会占用内存,但javaScript是有自己的内存回收机制,可以确定哪些变量不再需要,并将其清除。但是当你的代码存在逻辑缺陷的时,你以为被清除,但是程序还在着引用,导致程序运行完后并没有合适的回收所占用的空间,内存不断的被占用,运行的时间越长占用的就越多,随之出现的是,性能不佳,高延迟,频繁崩溃。

2,哪些情况会引起内存泄漏?

(1)意外的全局变量:未声明、由this创建 (2)闭包 (3)没有清理的DOM元素引用

3,减少内存泄漏

(1)减少不必要的全局变量或生命周期较长的对象,及时对无用的数据进行垃圾回收

(2)注意程序逻辑,避免‘死循环’

(3)避免创建过多对象