前端八股文(JS篇)

目录

1.数组有哪些原生方法?

2.substring和substr的区别

3.object.assign和扩展运算法是深拷贝还是浅拷贝,两者区别

4.new操作符的实现原理

5.for...in和for...of的区别

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

7.ajax,axios,fetch的区别

8.forEach和map方法有什么区别

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

10.你用过哪些设计模式


1.数组有哪些原生方法?

  • 数组和字符串的转换方法: toString(),toLocalString(),join(),其中join(方法可以指定转换为字符串时的分隔符。
  • 数组尾部的操作的方法pop()和push(),push方法可以传入多个参数。
  • 数组首部操作的方法shift()和unshift()重排序的方法reverse()和sort(),sort()方法可以传入一个函数来进行比较,传入前后两个值,如果返回值是正数,则交换两个参数的位置。
  • 数组的连接的方法concat(),返回的是拼接好的数组,不影响原数组。
  • 数组截取方法slice(),用于截取数组中的一部分返回,不影响原数组。
  • 数值插入方法splice(),影响原数组查找特定项的索引的方法,indexOf()和lastIndexOf()迭代方法every(),some(),filter(),map(),和forEach()方法
  • 数组归并方法reduce()和reduceRight()方法
  • 改变原数组的方法:fill(),pop(),push(),shift(),splice(),unshift(),reverse(),sort();
  • 不改变原数组的方法:concat(),every(),filter(),find(),findIndex(),forEach(),indeOf(),join(),lastIndexOf(),map(),reduce(),reduceRight(),slice(),some().

2.substring和substr的区别

它们都是字符串方法,用于截取字符串的一部分,主要区别在于参数不同

  • substring(startIndex,endIndex):接收两个参数,一个起始索引和结束索引,来指定字符串范围,如果省略第二个参数,则截取到字符串末尾。
  • substr(startIndex,length) :接收两个参数,并返回从startIndex开始,长度为length的子字符串。如果省略第二个参数,则截取到字符串末尾。
const str = "Hello, World!";

console.log(str.substring(0, 5)); // 输出: "Hello"

console.log(str.substr(7, 5)); // 输出: "World"

3.object.assign和扩展运算法是深拷贝还是浅拷贝,两者区别

都是浅拷贝

  • object.assign()方法接收的第一个参数作为目标对象,后面的所有参数作为源对象。然后把所有的源对象合并到目标对象中。它会修改一个对象,因此会触发ES6setter
  • 扩展操作符(...)使用它时,数组或对象中的每一个值都会被拷贝到一个新的数组或对象中。它不复制继承的属性或类的属性,但它会复制ES6的symbols属性

4.new操作符的实现原理

new操作符用来创建一个对象,并将该对象绑定到构造函数的this上。

new操作符的执行过程:

  1. 创建一个空对象
  2. 设置原型,将构造函数的原型指向空对象的prototype属性。
  3. 将this指向这个对象,通过apply执行构造函数。
  4. 判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象

5.for...in和for...of的区别

for...in和for...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循环可以用来遍历数组,类数组对象,字符串,set,map以及generator对象。


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

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

  • 创建一个XMLHttpReuqest对象。
  • 在这个对象使用open方法创建一个HTTP请求,open方法所需要的参数是请求的方法,请求的地址,是否异步和用户的认证信息。
  • 在发起请求前,可以为这个对象添加一些信息和监听函数。比如说可以通过setRequestHeader方法来为请求添加头信息。还可以为这个对象添加一个状态监听函数。一个XMLHttpRequest对象一共有5个状态,当他的状态变化时会触发onreadystatechange事件,可以通过设置监听函数,来处理请求成功后的结果。当对象的readyState变为4的时候,代表服务器返回的数据接收完成,这个时候可以通过判断请求的状态,如果状态时2xx或者304的话代表返回值正常。这个时候就可以通过response中的数据来对页面进行更新了。
  • 当对象的属性和监听函数设置完成后,最后调用send方法来向服务器发起请求,可以传入参数作为发送的数据体。
const SERVER_URL = "/server";
let xhr = new XMLHttpRequest();
// 创建 Http 请求
xhr.open("GET", url, true);
// 设置状态监听函数
xhr.onreadystatechange = function() {
  if (this.readyState !== 4) return;
  // 当请求成功时
  if (this.status === 200) {
    handle(this.response);
  } else {
    console.error(this.statusText);
  }
};
// 设置请求失败时的监听函数
xhr.onerror = function() {
  console.error(this.statusText);
};
// 设置请求头信息
xhr.responseType = "json";
xhr.setRequestHeader("Accept", "application/json");
// 发送 Http 请求
xhr.send(null);


7.ajax,axios,fetch的区别

ajax:

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

axios:

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

fetch:

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

8.forEach和map方法有什么区别

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

  • forEach()对数据的操作会改变原数组,该方法没有返回值
  • map()方法不会改变原数组的值,返回一个新数组,新数组中的值为原数组调用函数处理之后的值

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

尾调用就是在函数的最后一步调用函数,在一个函数里调用另外一个函数会保留当前执行的上下文,如果在函数尾部调用,因为已经是函数最后一步,所以这时可以不用保留当前的执行上下文,从而节省内存。但是ES6的尾调用只能在严格模式下开启,正常模式是无效的。


10.你用过哪些设计模式

  • 单例模式:保证类只有一个实例,并提供一个访问它的全局访问点。
  • 工厂模式:用来创建对象,根据不同的参数返回不同的对象实例。
  • 策略模式:定义一系列的算法,把它们一个个封装起来,并且使它们可以相互替换。
  • 装饰器模式:在不改变对象原型的基础上,对其进行包装扩展。
  • 观察者模式:定义了对象间一种一对多关系,当目标对象状态发生改变时,所有依赖它对对象都会得到通知。
  • 发布订阅模式: 基于一个主题/事件通道,希望接收通知的对象通过自定义事件订阅主题,被激活事件的对象(通过发布主题事件的方式被通知)。