JavaScript---八股

JavaScript

Promise

一.数据结构

1.JavaScript 有哪些数据类型

共有八个数据类型,分别是undefined,Null,Boolean,String,Number,Object,Symbol,Bigint

这些数据类型可以分为原始数据类型引用数据类型(复杂数据类型),他们在内存中的存储方式不同


其中 **Symbol** 和 **BigInt\*\* 是 ES6 中新增的数据类型:

  • **Symbol**代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题。
  • **BigInt** 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。

堆: 存放引用数据类型,引用数据类型占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址,如ObjectArrayFunction栈: 存放原始数据类型,栈中的简单数据段,占据空间小,属于被频繁使用的数据,如StringNumberNullBoolean

  • 堆: 存放引用数据类型,引用数据类型占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址,如ObjectArrayFunction
  • 栈: 存放原始数据类型,栈中的简单数据段,占据空间小,属于被频繁使用的数据,如StringNumberNullBoolean

2.Undefined 与 Null 的区别

至少从三个方面来讲: 1.undefind是声明之后的默认值,而Null却不是

2.undefined代表的含义是未定义,而 null 代表的含义是空对象

3.undefined在 JavaScript 中不是一个保留字,这就意味着可以用 undefined 来作为一个变 量名字,null 是一个关键字


UndefinedNull 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefinednull

  • undefined 代表的含义是未定义,一般变量声明了但还没有定义的时候会返回 undefinedtypeofundefined
  • null 代表的含义是空对象,null 主要用于赋值给一些可能会返回对象的变量,作为初始化,typeofobject

3.typeof null 的结果是什么,为什么?

1
Object

4.为什么 0.1 + 0.2 ≠ 0.3,如何让其相等

因为浮点数运算的精度问题。在计算机运行过程中,需要将数据转化成二进制,然后再进行计算。 因为浮点数自身小数位数的限制而截断的二进制在转化为十进制,就变成 0.30000000000000004,所以在计算时会产生误差。

解决方法:

方法一:

首先转化为整数,相加之后再转化为小数.具体做法为先乘 10 相加后除以 10

1
2
let x = (0.1 * 10 + 0.2 * 10) / 10;
console.log(x === 0.3);

方法二:

使用number对象的toFixed方法,只保留一位小数点

1
(n1 + n2).toFixed(2);

5.typeof NaN会返回什么?

会返回Number,他表示一个不能表示的数字

6.for…in…for…of…的区别

for…of… 遍历获取的是对象的键值,for…in…获取的是对象的键名

for...infor...of都是JavaScript中的循环语句,而for…of 是 ES6 新增的遍历方式,允许遍历一个含有iterator接口的数据结构(数组、对象等)并且返回各项的值,和ES3中的for…in的区别如下

  • for…of 遍历获取的是对象的键值for…in 获取的是对象的键名
  • for… in 会遍历对象的整个原型链,性能非常差不推荐使用,而 for … of 只遍历当前对象不会遍历原型链;
  • 对于数组的遍历,for…in 会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for…of 只返回数组的下标对应的属性值;

总结for...in 循环主要是为了遍历对象而生,不适用于遍历数组;for...of 循环可以用来遍历数组、类数组对象,字符串、SetMap 以及 Generator 对象。

7.对 AJAX 的理解,实现一个 AJAX 请求

AJAX是 Asynchronous JavaScript and XML 的缩写,指的是通过 JavaScript 的 异步通信,从服务器获取 XML 文档从中提取数据,再更新当前网页的对应部分,而不用刷新整个网页。 创建AJAX请求的步骤:

  • 创建一个 XMLHttpRequest 对象。
  • 在这个对象上使用 open 方法创建一个 HTTP 请求,open 方法所需要的参数是请求的方法、请求的地址、是否异步和用户的认证信息。
  • 在发起请求前,可以为这个对象添加一些信息和监听函数。比如说可以通过 setRequestHeader 方法来为请求添加头信息。还可以为这个对象添加一个状态监听函数。一个 XMLHttpRequest 对象一共有 5 个状态,当它的状态变化时会触发onreadystatechange 事件,可以通过设置监听函数,来处理请求成功后的结果。当对象的 readyState 变为 4 的时候,代表服务器返回的数据接收完成,这个时候可以通过判断请求的状态,如果状态是 2xx 或者 304 的话则代表返回正常。这个时候就可以通过 response 中的数据来对页面进行更新了。
  • 当对象的属性和监听函数设置完成后,最后调用 send 方法来向服务器发起请求,可以传入参数作为发送的数据体。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const serve_url = '/serve_url'

let xhr = new XMLHttpRequest()

//创建 hhtp 请求
xhr.open('GET', serve_url, true)

// 设置状态的监听函数
xhr.onreadystatechange = function(){
if(xhr.readyState !==4) {
return
}
if(xhr.status ===200 ){
hander(this.response)
}else[
console.error(this.statusText)
]
}

// 设置请求失败的监听函数
xhr.onerror = function() {
console.error(this.statusText)
}

// 设置请求头
xhr.responseType = 'json'
xhr.setRequestHeader('Content-Type', 'application/json')

// 发送http请求
xhr.send(

8.ajax,axios,fetch 的区别

ajax

  • 基于原生XHR开发,XHR本身架构不清晰。
  • 针对MVC编程,不符合现在前端 MVVM 的浪潮。
  • 多个请求之间如果有先后关系的话,就会出现回调地狱
  • 配置和调用方式非常混乱,而且基于事件的异步模型不友好。

axios

  • 支持PromiseAPI
  • 从浏览器中创建XMLHttpRequest
  • node.js 创建 http 请求
  • 支持请求拦截和响应拦截
  • 自动转换JSON数据
  • 客服端支持防止CSRF/XSRF

fetch

浏览器原生实现的请求方式,ajax 的替代品基于标准 Promise 实现,支持async/awaitfetchtch只对网络请求报错,对 400,500 都当做成功的请求,需要封装去处理默认不会带cookie,需要添加配置项fetch没有办法原生监测请求的进度,而XHR可以。

  • 浏览器原生实现的请求方式,ajax 的替代品
  • 基于标准 Promise 实现,支持async/await
  • fetchtch只对网络请求报错,对 400,500 都当做成功的请求,需要封装去处理
  • 默认不会带cookie,需要添加配置项
  • fetch没有办法原生监测请求的进度,而XHR可以。

9.forEach 和 map 的区别

两个方法都是用来遍历数组,区别如下:

  • forEach() 对数据的操作会改变原来的数据,这个方法没有返回值
  • map() 方法不会改变原来数组的值,会返回一个新的数组,新的数组中的值是原来的数组进行处理后的值

10.什么是尾调用,使用尾调用有什么好处