js常见面试题

54 阅读45分钟

1. 变量提升

    就是先使用后声明,从顺序上看;解析时,会把声明语句提上去,这就是变量提升

var  x =1 ;
console.log(x+'----'+y);//1----undefined
var y = 2;

//变量提升,先使用后声明
var  x =1 ;
y=2;
console.log(x+'----'+y);//1----2

2. 闭包

1. 闭包是什么?
闭包指有权访问另外一个函数作用域的变量的函数
闭包是js的一种语法特性,能读取其他函数内变量的函数
创建闭包的最常见的方式是:在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量

2. 为什么使用闭包
原因:在js中,函数内部可以直接读取全局变量,但是函数外部无法读取函数内的局部变量,我们需要得到函数内部的局部变量,那就是在函数内部中,再定义一个函数

3. 你能写一个闭包吗?
function outerFn(){
    var data = 10;
    var innerFn = function(){
    data += 1
    console.log(data)
  }
  return innerFn
}
var result = outerFn ()
result() //11
result() //12
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
名叫outerFn的函数,内部包含了一个已经声明的变量data和一个内部函数innerFn().一般情况下,是无法访问或修改data的,但是innerFn 可以访问data,我们通过调用return出的InnerFn, 就可以间接的去修改和访问到data的数据了。 这种方法叫做闭包。
------------------------------------------------------------------------------
Q: 那么如何访问或修改到一个函数内部的变量呢?
函数的return就是这个传送门,可以将一个内部函数送出外部函数,及时无法直接访问到外部函数内部的变量,也可以通过return出的内部函数去访问或修改外部函数的变量

4. 闭包的用途?
闭包可以用在很多地方,最好的是这两种
1. 读取函数内部的变量
2. 让这些内存的值始终保存在内存,不会调用后自动清除

5. 闭包的优缺点
优点:防止变量污染
缺点:更占内存,会导致网页性能变差,在IE下容易造成内存泄漏,必要的时候,及时手动释放闭包函数

6. 内存泄漏是什么?怎么解决
内存泄漏是指你用不到(访问不到)的变量,依然占据着内存空间,不能再次利用
解决方法:
  1. 退出函数之前,将不使用的局部变量赋值为null
  2. 避免变量的循环赋值和引用
  3. 利用JQuery释放自身指定的所有事件处理程序
由于jQuery考虑到了内存泄漏的危害,它会手动释放自己指定的所有事件处理程序。只要坚持使用jquery的事件绑定,就可以一定程度上避免这种特定的原因导致的内存泄漏

7. 闭包解决了什么问题
  1.不必为函数命名,避免污染全局变量;  2.提供对局部变量的间接访问,按需求进行共享和长期保存;  3.维持变量,使其不被垃圾回收。  4.内部形成单独的块级作用域,通过闭包实现变量/方法的私有化

8 使用闭包的tips
  1.由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
  2.闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

9. 垃圾回收机制
  垃圾回收是一种自动的内存管理机制,当一个电脑上动态内存不在需要时,就应该予以释放,让出内存,这种内存资源管理,称为垃圾回收
  垃圾回收方法有标记清除,引用计数
标记清除:从根集合触发,标记处需要回收的对象,清除被标记的对象
引用计数:就是记录每个对象被引用的次数,每次新建对象、赋值引用和删除引用的同时更新计数器,如果计数器值为0则直接回收内存。很明显,引用计数最大的优势是暂停时间短。

阮一峰老师写的教程
www.ruanyifeng.com/blog/2009/0…

3. 3种强制类型转换和2种隐式类型转换?

强制(parseInt, parseFloat, number

隐式(== === + -

 4. js操作数组的方法

不改变原数组
1. concat() 连接数组 
arr1.concat(arr2)连接两个或多个数组,返回一个新的数组
const arr1 = [1, 2, 3]
const arr2 = [4, 5]
const newArr = arr1.concat(arr2)
console.log(newArr) // [1, 2, 3, 4, 5]

2.join() 不改变原数组
join(str) 数组转成字符串,方法只接受一个参数,默认为逗号分隔符
const arr = [1, 2, 3]
console.log(arr) // [1, 2, 3]
console.log(arr.join()) // 1,2,3
console.log(arr.join(':')) // 1:2:3

join() 实现重复字符串

const str = new Array(4).join('啦')
console.log(str) // 啦啦啦
4个数有三个空,插入3

3. push | unshift()  改变原数组

push 像数组的末尾添加一个或多个元素,并返回新的长度
unshift() 向数组的开头添加一个或多个元素,并返回新的长度

4.shift() & pop() 删除元素操作,改变了原数组

pop() 删除并返回数组最后一个元素
shift() 删除并返回数组第一个元素

5. sort() 数组排序,改变原数组

const arr = [2, 4, 3, 1]
console.log(arr.sort()) // [1, 2, 3, 4]
console.log(arr) // [1, 2, 3, 4]

sort() 不按照数组元素数值的大小对数字进行排序,是按照字符编码的顺序进行排序,那怎么样根据元素数值大小
进行排序呢?
const arr = [2, 4, 3, 1]
const arr1 = [...arr].sort((a, b) => a - b)
const arr2 = [...arr].sort((a, b) => b - a)
console.log(arr1) // [1, 2, 3, 4]
console.log(arr2) // [4, 3, 2, 1]

6. reverse() 反转数组,改变原数组

const arr = [2, 4, 3, 1]
console.log(arr.reverse()) // [1, 3, 4, 2]
console.log(arr) // [1, 3, 4, 2]

7. splice() 更新数组,改变原数组

arr.splice(index, howmany, item1, ..., itemX) 向/从数组中添加/删除项目,然后返回被删除的项目,返回含有被删除的元素的数组,若没有删除元素则返回一个空数组

8. slice() 更新数组,不改变原数组

 arr.slice(start,end) 从start开始选取,不包括该元素,从end处结束选取,如果为空的话,那么选取

从start到数组结束的所有元素,负数代表方向,从数组尾部开始计算位置
const arr = [1, 2, 3, 4, 6]
console.log(arr.slice(1)) // [2, 3, 4, 6]
console.log(arr.slice(1, -2)) // [2, 3]
console.log(arr.slice(-3, 1)) // [2]
console.log(arr) // [1, 2, 3, 4, 6]

// 从原数组中选定元素的数组

// 注意:这个不会改变原始数组

// array.slice(start,end)

/**

* 获取新数组,内容从arr的角标3开始一直到结尾的所有元素,

*/

let arr1 = [1, 3, 5, 7, 9];

let newArr1 = arr1.slice(3);

console.log(arr1); // [1, 3, 5, 7, 9]

console.log(newArr1); //[7, 9]

/**

* 获取新数组,内容从arr的角标3开始角标4结束(不包含角标4元素)

*/

let arr2 = [1, 3, 5, 7, 9];

let newArr2 = arr2.slice(3, 4);

console.log(arr2); // [1, 3, 5, 7, 9]

console.log(newArr2); //[7]

9. slice ,splice区别

  // splice 修改原数组,slice不修改  // splice可以删除,修改,替换原数组,slice只能截取数组中的值并生成新数组  // splice可传递多个参数,slice最多只能传递两个参数

10 indexOf ,lastIndexOf