JS面试题

175 阅读6分钟

1. underfind出现的4种情况

  • 声明未赋值
  • 对象属性不存在
  • 函数调用少了参数
  • 函数的默认返回值

2. filter

  • current=>当前遍历值,index=>下标,array=>元数组
  • 特点:不会改变原数组
let arr = [1,2,3,4,5];
let newArr = arr.filter((current,index,array)=> current > 2)
console.log(arr); //[1,2,3,4,5]
console.log(newArr); //[3,4,5]

3. forEach和map

  • forEach特点
    • 没有返回值
    • 不能被break中断
    • 遍历的是value值
  • map特点
    • 有返回值,返回数组
    • 不能被break中断
    • 接受的参数为函数(value,index)

4. 递归 优化递归计算慢的问题:使用尾递归=>函数最后调用一个函数

// 求1~10的和
function sum(num1,num2){
    let num = num1 + num2;
    if(num2+1 > 10) return num;
    return sum(num, num2+1)
}
let sums = sum(1,2)

5. 闭包

  • 闭包是什么?=> 方法里面返回一个方法,有权访问另外一个函数作用域中的变量
  • 为什么要闭包
    • 为了在函数外部访问函数内部变量 (沟通内外部方法的桥梁)
    • 保护私有变量不被内存回收机制回收(延长变量生命周期,不会造成全局污染)
    • 创建私有环境
  • 应用场景 => 防抖与节流(体现了闭包的延长生命周期)
  • 如何防止内存泄漏=> 在退出函数之前,将不使用的局部变量全部删除(str = null)
function fun1(){
    let str = '闭包';
    return function(){
        return str;
    }
}

6. 作用域链

  • 就近原则查找
function a(){
    let str = 1;
    function b(){
        let str = 2;
        function c(){
            console.log(str); // 2
        }
    }
}

7. 防抖与节流

  • 什么是防抖=> 固定时间内,只允许请求一次
    • 例子 Select下拉框数据根据框内输入动态获取,用户输的快数据获取容易发生抖动,设计一个定时器可以在两秒后发起请求。
  • 什么是节流=> 一定时间内,将多个请求合并成一次请求
  • 什么时候用=> 提交表单,高频监听事件
    • 例子 用户在提交资料时不停的点击提交,在一定时间内只处理用户的一次请求。

8. 原型与原型链

  • 什么是原型=> prototype

    • 只有函数才有原型
    • 例子 => function fun(){}; fun.prototype.(name || fun2)= '原型' || function(){}; //为什么要在原型上面赋值=> 为了原型链的继承
  • 什么是原型链=> 两种展现形式 proto / [[prototype]]

    • 任何数据如对象数组都有原型链
    • 原型链继承是一层一层往上找,直到null,原型链最顶端为null
    • 判断是否为函数私有属性 实例.hasOwnProperty(属性),会打印出私有属性

9. 值类型和引用类型

值类型

  • 直接访问数据的值。
  • 如(int float 布尔)
  • 存储在栈中
  • 初始值为0
  • 继承自System.ValueType

引用类型

  • 访问数据的存储地址
  • 如(数组 对象)
  • 值在堆中,地址在栈中
  • 初始值为null
  • 继承自System.Object。

10. 判断数据类型

  • typeof (基础数据类型)
  • array instanceof Array(判断是否给定类型)
  • constructor arr.constructor===Array(判断是否为某构造函数的实例)(constructor构造器:在对象创建或者实例化时候被调用的方法,用该方法来初始化数据和资源)

11. 编程方式

  • 命令式编程 => 代码一步一步的执行
  • 函数式编程 => 把运算过程抽象成一个个函数,如(一个函数中有加和乘,函数式编程会写成两个函数,一个加,一个乘)特征:
    • 函数可以作为参数
    • 可以作为函数的返回值
    • 函数可以赋值给变量
    • 函数是纯函数(纯函数特征:不依赖外部变量,不改变本身之外的变量)
    • 函数组合compose => 将多个函数合并成一个函数
  • 面向对象编程 => 把现实世界的事物抽象成类和对象模型,通过这些模型构建应用程序功能,描述一个类就去new一个类

12. arguments

  • arguments是接收函数参数的一个类数组对象,我们叫他伪数组
  • arguments.length传过来的函数参数个数
  • arguments转成真的数组 [].slice.call(arguments);
  • arguments[0] = 20; 修改值
  • 接受参数的函数名.apply(this, arguments); 将参数传到另一个函数
  • ES6 中可以用扩展运算符展开得到参数 ...arguments

13. this =>在js中代表的是作用域,遵循谁调用指向谁=>当前上级

14. .call()和.apply()和.bind()

  • B.call(A, args1);即A对象调用B对象的方法,改变this指向
  • B.apply(A, arguments),即A对象应用B对象的方法,改变this指向
  • bind() 只改变this指向,不执行

15. 深拷贝和浅拷贝=>只适用于引用类型

  • 深拷贝 => 在内存中重新创建储存空间, 不会改变原值
    • 解构赋值是不是深拷贝?=> 一维数组是深拷贝,二维是浅拷贝
    • 日常用到的深拷贝,JSON.parse(),JSON.stringify()
    • 弊端 => 不能拷贝所有的js关键字(如:null,function...)
    • 手写深拷贝 => 1、定义一个变量判断是数组还是对象 2、通过for循环拷贝值(基本值直接复制,引用类型值使用递归)
  • 浅拷贝 => 表示只拷贝了在内存中的地址 (例:let arr = [1,2]; arr.push(3)=> arr =[1,2,3])

16. 栈和堆

  • 先进后出
  • 自动分配和释放内存空间
  • 基本类型存在栈

  • 引用类型的值存在堆,地址存在栈(先去栈拿地址,再去堆取值)
  • 在没有任何变量引用时会被垃圾回收机制回收

17.虚拟dom

  • 意义 => 初始化生成虚拟dom,后续高效更新dom
  • 是什么 => 一个js对象
  • 作用 => 初始化时将真实dom转换成虚拟dom,之后通过对象对比更新真实dom
    • 虚拟dom对象比较是执行效率的快慢
    • 操作真实dom会消耗浏览器性能
  • 结构
    • 目标元素(谁的虚拟dom)
    • 属性 (class style click)
    • children 子元素

18.xss和csrf攻击

  • XSS => 跨站脚本攻击 => 通过注入脚本获取信息 => 可以使用前后端分离,前端渲染,后端负责数据
  • CSRF => 跨站请求伪造 => 使用cookie假冒用户进行操作 => 可以使用token,或者开启严格模式

19.解决跨域

  • JsonP => 前端通过script发送一个get请求来解决,并且请求参数为一个函数
  • Cors => 后端通过添加请求头来解决

20. 宏任务和微任务 执行顺序:同步任务执行=>微任务执行=>宏任务

  • 宏任务 => 如settimeout,promise
  • 微任务 => 如promise.then()