前端面试宝典总结3-JavaScript(2)

时间:2024-06-08 07:18:24

前端面试宝典总结之JavaScript(2)

本文章 对各大学习技术论坛知识点,进行总结、归纳自用学习,共勉????

上一篇????: 前端面试宝典总结3-JavaScript(1)

文章目录

  • 前端面试宝典总结之JavaScript(2)
  • 1.常用的正则表达式有哪些?
  • 2.JavaScript有哪些内置对象
  • 3. 对JSON的理解
  • 4.JavaScript脚本延迟加载的方式有哪些?
  • 5.JavaScript 类数组对象的定义?
  • 6.数组有哪些原生方法?
  • 7.Unicode、UTF-8、UTF-16、UTF-32的区别?
  • 8. new操作符的实现原理
  • 9. map和Object的区别
  • 10.map和weakMap的区别

1.常用的正则表达式有哪些?

//用户名正则,4到16位(字母,数字,下划线,减号)
var uPattern = /^[a-zA-Z0-9_-]{4,16}$/;

//密码强度正则,最少6位,包括至少1个大写字母,1个小写字母,1个数字,1个特殊字符
var pPattern = /^.*(?=.{6,})(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?=.*[!@#$%^&*? ]).*$/;

//身份证号(18位)正则
var idPattern = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;

//手机号正则
var mPattern = /^1[34578]\d{9}$/; 

//正整数正则
var posPattern = /^\d+$/;
//负整数正则
var negPattern = /^-\d+$/;
//整数正则
var intPattern = /^-?\d+$/;

//正数正则
var posPattern = /^\d*\.?\d+$/;
//负数正则
var negPattern = /^-\d*\.?\d+$/;
//数字正则
var numPattern = /^-?\d*\.?\d+$/;

//Email正则
var ePattern = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;

//URL正则
var urlP= /^((https?|ftp|file):\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/;

//QQ号正则,5至11位
var qqPattern = /^[1-9][0-9]{4,10}$/;

//微信号正则,6至20位,以字母开头,字母,数字,减号,下划线
var wxPattern = /^[a-zA-Z]([-_a-zA-Z0-9]{5,19})+$/;

//车牌号正则
var cPattern = /^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$/;

//包含中文正则
var cnPattern = /[\u4E00-\u9FA5]/;

2.JavaScript有哪些内置对象

全局的对象( global objects )或称标准内置对象,不要和 “全局对象(global object)” 混淆。这里说的全局的对象是说在全局作用域里的对象。全局作用域中的其他对象可以由用户的脚本创建或由宿主程序提供。

基础值对象:

  • Infinity: 表示无穷大。
  • NaN: 表示非数字值。
  • undefined: 表示未定义的原始值

基础函数对象:

  • eval(): 执行JavaScript代码字符串。
  • parseInt(), parseFloat(): 分别解析整数和浮点数。
  • isFinite(), isNaN(): 检查数值是否有限或是否为NaN

基本构造函数:

  • Object: 所有对象的基类。
  • Function: 函数的构造函数。
  • Boolean, String, Number, Symbol: 布尔、字符串、数字和符号的构造函数。
  • Error: 错误对象的基类,包括子类如TypeError, ReferenceError等。

数学与日期:

  • Math: 提供数学常数和函数。
  • Date: 表示日期和时间。

文本处理:

  • String: 提供字符串操作方法。
  • RegExp: 正则表达式,用于文本匹配和替换。

集合对象:

  • Array: 数组。
  • TypedArrays: 用于处理二进制数据的类型化数组。
  • Map, Set: 键值对集合和唯一值集合。
  • WeakMap, WeakSet: 类似于Map和Set,但键是弱引用,适合垃圾回收。

矢量和数据处理:

  • SIMD: 单指令多数据,用于高性能数值计算。
  • Buffer, TypedArray: Node.js中的二进制数据处理。

异步与控制抽象:

  • Promise: 用于异步编程的解决回调地狱。
  • Generator: 生成器函数,支持暂停和恢复函数执行。
  • async/await: 基于Promise的异步编程糖衣语法

反射与元编程:

  • Reflect: 提供对象操作的静态方法。
  • Proxy: 用于创建对象的代理,拦截并自定义操作行为。

国际化:

  • Intl: 国际化和本地化支持,包括Collator, DateTimeFormat等。

Web平台特有:

  • WebAssembly: 面向Web的低级编程语言。
  • DOM, BOM: 浏览器环境中的文档对象模型和浏览器对象模型。

特殊对象:

  • arguments: 函数调用时的局部变量,包含传入的参数。

这些内置对象共同构成了JavaScript强大的生态系统,使得开发者能够应对各种复杂的编程需求,从基本的数据处理到高级的异步控制和性能优化。

3. 对JSON的理解

JSON 是一种基于文本的轻量级的数据交换格式。它可以被任何的编程语言读取和作为数据格式来传递。

在项目开发中,使用 JSON 作为前后端数据交换的方式。在前端通过将一个符合 JSON 格式的数据结构序列化为

JSON 字符串,然后将它传递到后端,后端通过 JSON 格式的字符串解析后生成对应的数据结构,以此来实现前后端数据的一个传递。

因为 JSON 的语法是基于 js 的,因此很容易将 JSON 和 js 中的对象弄混,但是应该注意的是 JSON 和 js 中的对象不是一回事,JSON 中对象格式更加严格,比如说在 JSON 中属性值不能为函数,不能出现 NaN 这样的属性值等,因此大多数的 js 对象是不符合 JSON 对象的格式的。

在 js 中提供了两个函数来实现 js 数据结构和 JSON 格式的转换处理,

  • JSON.stringify 函数,通过传入一个符合 JSON 格式的数据结构,将其转换为一个 JSON 字符串。如果传入的数据结构不符合
    JSON 格式,那么在序列化的时候会对这些值进行对应的特殊处理,使其符合规范。在前端向后端发送数据时,可以调用这个函数将数据对象转化为JSON 格式的字符串。
  • JSON.parse() 函数,这个函数用来将 JSON 格式的字符串转换为一个 js 数据结构,如果传入的字符串不是标准的 JSON
    格式的字符串的话,将会抛出错误。当从后端接收到 JSON 格式的字符串时,可以通过这个方法来将其解析为一个 js数据结构,以此来进行数据的访问。

4.JavaScript脚本延迟加载的方式有哪些?

延迟加载就是等页面加载完成之后再加载 JavaScript 文件。 js 延迟加载有助于提高页面加载速度。

一般有以下几种方式:

  • defer 属性:给 js 脚本添加 defer属性,这个属性会让脚本的加载与文档的解析同步解析,然后在文档解析完成后再执行这个脚本文件,这样的话就能使页面的渲染不被阻塞。多个设置了
    defer 属性的脚本按规范来说最后是顺序执行的,但是在一些浏览器中可能不是这样。
  • async 属性:给 js 脚本添加 async 属性,这个属性会使脚本异步加载,不会阻塞页面的解析过程,但是当脚本加载完成后立即执行js 脚本,这个时候如果文档没有解析完成的话同样会阻塞。多个 async属性的脚本的执行顺序是不可预测的,一般不会按照代码的顺序依次执行。
  • 动态创建 DOM 方式:动态创建 DOM 标签的方式,可以对文档的加载事件进行监听,当文档加载完成后再动态的创建 script标签来引入 js 脚本。
  • 使用 setTimeout 延迟方法:设置一个定时器来延迟加载js脚本文件
  • 让 JS 最后加载:将 js 脚本放在文档的底部,来使 js 脚本尽可能的在最后来加载执行。

5.JavaScript 类数组对象的定义?

一个拥有 length 属性和若干索引属性的对象就可以被称为类数组对象,类数组对象和数组类似,但是不能调用数组的方法。常见的类数组对象有 arguments 和 DOM 方法的返回结果,还有一个函数也可以被看作是类数组对象,因为它含有 length 属性值,代表可接收的参数个数。

常见的类数组转换为数组的方法有这样几种:
(1)通过 call 调用数组的 slice 方法来实现转换

Array.prototype.slice.call(arrayLike);

(2)通过 call 调用数组的 splice 方法来实现转换

Array.prototype.splice.call(arrayLike, 0);

(3)通过 apply 调用数组的 concat 方法来实现转换

Array.prototype.concat.apply([], arrayLike);

(4)通过 Array.from 方法来实现转换

Array.from(arrayLike);

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

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

7.Unicode、UTF-8、UTF-16、UTF-32的区别?

8. new操作符的实现原理

new操作符的执行过程:
(1)首先创建了一个新的空对象
(2)设置原型,将对象的原型设置为函数的 prototype 对象。
(3)让函数的 this 指向这个对象,执行构造函数的代码(为这个新对象添加属性)
(4)判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象。

function objectFactory() {
  let newObject = null;
  let constructor = Array.prototype.shift.call(arguments);
  let result = null;
  // 判断参数是否是一个函数
  if (typeof constructor !== "function") {
    console.error("type error");
    return;
  }
  // 新建一个空对象,对象的原型为构造函数的 prototype 对象
  newObject = Object.create(constructor.prototype);
  // 将 this 指向新建对象,并执行函数
  result = constructor.apply(newObject, arguments);
  // 判断返回对象
  let flag = result && (typeof result === "object" || typeof result === "function");
  // 判断返回结果
  return flag ? result : newObject;
}
// 使用方法
objectFactory(构造函数, 初始化参数);

9. map和Object的区别

特性 Map Object
意外的键 Map默认不含任何意外键,仅含显式插入的键,避免原型链冲突。 Object具有原型链,可能导致键名冲突。
键的类型 键可以是任意类型,包括函数、对象或基本类型。 键必须为字符串或Symbol。
键的顺序 有序,迭代时按照插入顺序返回键值。 无序,迭代时不保证键的顺序。
获取大小 直接使用 .size 属性获取键值对数量。 需要手动计算或遍历获取键值对数量。
迭代 自身是可迭代的,可直接用 for...of 循环遍历。 需通过 Object.keys()Object.entries() 等方法获取键集后迭代。
性能 在频繁增删键值对场景下性能更优。 频繁增删键值对操作未专门优化,大数据量下可能表现不佳。

10.map和weakMap的区别

(1)Map
map本质上就是键值对的集合,但是普通的Object中的键值对中的键只能是字符串。而ES6提供的Map数据结构类似于对象,但是它的键不限制范围,可以是任意类型,是一种更加完善的Hash结构。如果Map的键是一个原始数据类型,只要两个键严格相同,就视为是同一个键。

实际上Map是一个数组,它的每一个数据也都是一个数组,其形式如下:

const map = [
     ["name","李蛋蛋"],
     ["age",18],
]

Map数据结构有以下操作方法:

  • size: map.size 返回Map结构的成员总数。
  • set(key,value):设置键名key对应的键值value,然后返回整个Map结构,如果key已经有值,则键值会被更新,否则就新生成该键。(因为返回的是当前Map对象,所以可以链式调用)
  • get(key):该方法读取key对应的键值,如果找不到key,返回undefined。
  • has(key):该方法返回一个布尔值,表示某个键是否在当前Map对象中。
  • delete(key):该方法删除某个键,返回true,如果删除失败,返回false。
  • clear():map.clear()清除所有成员,没有返回值。

Map结构原生提供是三个遍历器生成函数和一个遍历方法

  • keys():返回键名的遍历器。
  • values():返回键值的遍历器。
  • entries():返回所有成员的遍历器。
  • forEach():遍历Map的所有成员。
const map = new Map([
     ["foo",1],
     ["bar",2],
])
for(let key of map.keys()){
    console.log(key);  // foo bar
}
for(let value of map.values()){
     console.log(value); // 1 2
}
for(let items of map.entries()){
    console.log(items);  // ["foo",1]  ["bar",2]
}
map.forEach( (value,key,map) => {
     console.log(key,value); // foo 1    bar 2
})

(2)WeakMap
WeakMap 对象也是一组键值对的集合,其中的键是弱引用的。其键必须是对象,原始数据类型不能作为key值,而值可以是任意的。

该对象也有以下几种方法:

  • set(key,value):设置键名key对应的键值value,然后返回整个Map结构,如果key已经有值,则键值会被更新,否则就新生成该键。(因为返回的是当前Map对象,所以可以链式调用)

  • get(key):该方法读取key对应的键值,如果找不到key,返回undefined

  • has(key):该方法返回一个布尔值,表示某个键是否在当前Map对象中。

  • delete(key):该方法删除某个键,返回true,如果删除失败,返回false

clear()方法已经被弃用,所以可以通过创建一个空的WeakMap并替换原对象来实现清除。

WeakMap的设计目的在于,有时想在某个对象上面存放一些数据,但是这会形成对于这个对象的引用。一旦不再需要这两个对象,就必须手动删除这个引用,否则垃圾回收机制就不会释放对象占用的内存。

WeakMap的键名所引用的对象都是弱引用,即垃圾回收机制不将该引用考虑在内。因此,只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。

总结:

  • Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
  • WeakMap 结构与 Map 结构类似,也是用于生成键值对的集合。但是 WeakMap 只接受对象作为键名( null 除外),不接受其他类型的值作为键名。而且 WeakMap 的键名所指向的对象,不计入垃圾回收机制。

下一篇????: 前端面试宝典总结4-手搓代码(数据处理)