javaScript---javaScript面试题

目录

1.JavaScript和Java是什么关系

2.==和===

3.var let const区别

4.new的执行过程

5.call bind apply的区别

6.Js数据类型及区别

7.如何判断一个对象为数组

8.JavaScript判断变量类型的方法

9.闭包

10.原型链

11.作用域与作用域链

12.为什么要使用模块化?实现模块化的方式?

13.ES Module和CommonJs区别

14.js如何实现继承

15.Promise

17.async和await

18.async/await 和 Promise 的关系

19.深拷贝与浅拷贝

20.防抖和节流

21.同步和异步的区别

22.es6有哪些新特性?

23.es7新特性

24.数组去重的方法

25.什么原因会造成内存泄露

26.浏览器和nodejs的事件循环

26.axios 是什么,其特点和常用语法

27.事件的触发过程是怎么样的?

29.普通函数和箭头函数的区别

30.JS内存泄露如何检测?场景有哪些?


1.JavaScript和Java是什么关系

JavaJavascript的关系就像雷锋和雷峰塔的关系,也像老婆和老婆饼的关系。JavaJavaScript是两门不同的编程语言。

相同之处

  • 它们的语法和C语言都很相似;
  • 都是面向对象的(虽然实现的方式略有不同);
  • JavaScript在设计时参照了Java的命名规则;

不同之处

  • JavaScript是动态类型语言(类型检查在运行时期进行),而Java是静态类型语言(类型检查在编译时期进行)
  • JavaScript是弱类型的,Java属于强类型
  • JavaScript的面向对象是基于原型(prototype-based)实现的,Java是基于类(class-based)的;

JavaScript除了长得和Java比较像之外,语言风格相去甚远。JavaScript在设计时所参考的对象不包括Java,而包括了像Self和Scheme这样的语言。

2.==和===

==:先进行类型转换,再对值进行比较,判断值是否相等,相等则为true 不等就为false

===:全等,不做类型转换,判断类型和值是否都相等 相等则为true 不等为false

3.var let const区别

(1)var声明的变量会挂载在window上,而let和const声明的变量不会

(2)var声明变量存在变量提升,let和const不存在变量提升

(3)var 不具备块级作用域,会造成变量穿透,let,const具有块级作用域({},如for,if都是),不会造成穿透

(4)同一作用域下,var可以重复声明,而let和const不能声明同名变量

(5)let,const会造成暂时性死区(不能先使用再声明)

(6)const一旦声明必须赋值,不能写成【const a】,但是【const a=null】是合法的,但赋值后其值不能修改。如果声明的是复合类型数据,可以修改其属性

4.new的执行过程

1.开辟内存空间;2.this指向内存空间;3.执行构造函数;4.返回this实例

5.call bind apply的区别

call()、apply()、bind() 都是用来重定义 this 这个对象

function.apply(thisArg, [argsArray])//argsArray 是一个可选的数组

function.call(thisArg, arg1, arg2, ...)//arg1、arg2、... 是将传递给函数的参数列表

function.bind(thisArg, arg1, arg2, ...)//arg1、arg2、... 是一些可选的参数,这些参数将在调用新函数时作为参数列表传递给原函数

相同点:第一个参数thisArg 表示函数要绑定的上下文,是用来改变函数this指向的,第二个参数是是用于传参

不同点:

call 和apply可以直接调用,bind不会立即调用函数,而是会返回一个新的函数。

call和bind可以传递多个参数,apply只能传递一个参数 (数组或者伪数组)

function test(a, b) {
  console.log(a + b);
}
test.call({ name: "call" }, 1, 2); //3
test.apply({ name: "apply" }, [2, 3]); //5
const test1 = test.bind({ name: "bind" }, 4);
console.log(test1); //[Function: bound test]
test1(2); //6

6.Js数据类型及区别

值类型(基本类型):字符串(String)、数字(Number)、BigInt、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol

BigInt:ES11引入的新的基本数据类型。BigInt数据类型的目的是比Number数据类型支持的范围更大的整数值,以任意精度表示整数。使用 BigInt解决了之前Number整数溢出的问题。

Symbol是ES6新出的一种数据类型,这种数据类型的特点就是没有重复的数据,可以作为object的key。

引用数据类型(对象类型):对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)

区别:

  • 基本类型存储在栈中,空间小,操作频繁
  • 引用数据类型存放在堆中,它的地址在栈中,一般我们访问就是它的地址

7.如何判断一个对象为数组

最可靠的两种方式为Array.isArray(arr) ;Object.prototype.toString.call(arr)==''[object Array]'' 。另外可以使用arr instanceof Array 及借助构造函数和原型的方式判断。

注意:typepf操作符可以用来检测给定变量的数据类型,返回的值有以下几种:undefined,boolean,string,number,object,function。

使用typeof检测以下数据类型返回都为object: null,数组,json对象,Date,RegExp,因此不能用来判断是否为数组类型。

typeof对于原始类型来说,除了null都可以显示正确的类型;typeof对于对象来说,除了函数都会显示object,所以说typeof并不能准确判断变量到底是什么类型。

判断一个对象为数组的方法如下

arr=[1,2,3];

1)Array.isArray(arr) //true

2)arr instanceof Array  //true 构造函数判断,instanceof操作符可以来表示实例是否属于某个构造函数创建的,内部机制是通过原型链来判断的

3)arr.constructor == Array //true 构造函数

4)Array.prototype.isPrototypeOf(arr)//true原型

5)Object.getPrototypeOf(arr) == Array.prototype  //true

6)arr.__proto__ == Array.prototype //true

7)Object.prototype.toString.call(arr)==''[object Array]''  // true 根据对象的class属性来判断,class:每个对象的内部属性,记录创建对象时使用的类型名,一旦创建,无法修改。

以上方法中,最可靠的为第1种和第7种,因为对象的原型指向可以修改

var obj={}; obj.__proto__=Array.prototype;//修改原型指向

8.JavaScript判断变量类型的方法

JavaScript有4种方法判断变量的类型,分别是typeof、instanceof、Object.prototype.toString.call()(对象原型链判断方法)、 constructor (用于引用数据类型)

typeof:常用于判断基本数据类型(typeof null返回object),对于引用数据类型除了function返回function,其余全部返回object。

instanceof:主要用于区分引用数据类型,检测方法是检测的类型在当前实例的原型链上,用其检测出来的结果都是true,不太适合用于简单数据类型的检测,检测过程繁琐且对于简单数据类型中的undefined, null, symbol检测不出来。

constructor:用于检测引用数据类型,检测方法是获取实例的构造函数判断和某个类是否相同,如果相同就说明该数据是符合那个数据类型的,这种方法不会把原型链上的其他类也加入进来,避免了原型链的干扰。

Object.prototype.toString.call(arr):检测最可靠,返回的是该数据类型的字符串

9.闭包

简单说就是子函数可以使用父函数的局部变量

定义:函数A内部有一个函数B,函数B可以访问到函数A中的变量,那么函数B就是闭包

优点:既可以长久的保存变量又不会造成全局污染,闭包使得函数内部的变量在函数执行完后, 仍然存活在内存中(延长了局部变量的生命周期),让函数外部可以操作(读写)到函数内部的数据(变量/函数)。

缺点闭包的缺点就是常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。

10.原型链

对象拥有__proto__隐式原型属性和constructor属性

函数拥有prototype显式原型属性和__proto__隐式原型属性、constructor属性(JS中函数也是一种对象)。

__proto__隐式原型属性的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,一直找,直到__proto__属性的终点null,再往上找就相当于在null上取值,会报错。通过__proto__属性将对象连接起来的这条链路即我们所谓的原型链。

  • 原型:每一个 JavaScript 对象(null 除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性,其实就是 prototype 对象。
  • 原型链:由相互关联的原型组成的链状结构就是原型链。

javaScript---原型链 __proto__、constructor、prototype_maidu_xbd的博客-CSDN博客

11.作用域与作用域链

作用域:规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。换句话说,作用域决定了代码区块中变量和其他资源的可见性。(全局作用域、函数作用域、块级作用域)

作用域链:从当前作用域开始一层层往上找某个变量,如果找到全局作用域还没找到,就放弃寻找 。这种层级关系就是作用域链。

12.为什么要使用模块化?实现模块化的方式?

模块化的优点解决命名冲突;提供复用性;提高代码可维护性

实现模块化的方式立即执行函数;AMD和CMD;common.js;ES Module

(1)立即执行函数:在早期,使用立即执行函数实现模块化是常见的手段,通过函数作用域解决了命名冲突、污染全局作用域的问题

(function(globalVariable){
globalVariable.test = function() {}
// ... 声明各种变量、函数都不会污染全局作用域
})(globalVariable)

(2)AMD 和 CMD(这两种方式目前很少见到了)

// AMD
define(['./a', './b'], function(a, b) {
// 加载模块完毕可以使用
a.do()
b.do()
})
// CMD
define(function(require, exports, module) {
// 加载模块
// 可以把 require 写在函数体的任意地方实现延迟加载
var a = require('./a')
a.doSomething()
})

(3)CommonJs:CommonJS最早是Node在使用,目前也仍然广泛使用,比如在Webpack中你就能见到它,当然目前在Node中的模块管理已经和CommonJS有一些区别了

// a.js
module.exports = {
a: 1
}
// or
exports.a = 1

// b.js
var module = require('./a.js')
module.a // -> log 1

(4)ES Module:ES Module是原生实现的模块化方案

// 引入模块 API
import XXX from './a.js'
import { XXX } from './a.js'
// 导出模块 API
export function a() {}
export default function() {}

*13.ES Module和CommonJs区别

  • CommonJS支持动态导入,也就是require(${path}/xx.js),后者目前不支持,但是已有提案
  • CommonJS是同步导入,因为用于服务端,文件都在本地,同步导入即使卡住主线程影响也不大。而ES Module是异步导入,因为用于浏览器,需要下载文件,如果也采用同步导入会对渲染有很大影响
  • CommonJS在导出时都是值拷贝,就算导出的值变了,导入的值也不会改变,所以如果想更新值,必须重新导入一次。但是ES Module采用实时绑定的方式,导入导出的值都指向同一个内存地址,所以导入值会跟随导出值变化
  • ES Module会编译成require/exports来执行的

14.js如何实现继承

javaScript---js如何实现继承_maidu_xbd的博客-CSDN博客

15.Promise

Promise是一种异步编程的解决方案。Promise是ES6提供的一个构造函数,可以使用Promise构造函数new一个实例,Promise构造函数接收一个函数作为参数,这个函数有两个参数,分别是两个函数 resolve和reject ,有三种状态,pending(进行中)、fulfilled(已完成)、rejected(已失败),只要Promise 的状态发生了变化,之后就再也不会改变,就像整个 Promise 实例凝固了

特性:①代码立即执行 ②状态的不可逆性 ③回调异步性④链式调用

Promise作用:Promise是异步微任务,解决了异步多层嵌套回调的问题,让代码的可读性更高,更容易维护。

promise使用:

(1)当Promise的状态由pending转变为fulfilled,执行resolve,传递异步操作的结果。

(2)当Promise的状态由pending转变为rejected时,执行reject,传递异步操作报出的错误。

(3)实例创建完成后,可以使用then方法分别指定成功或失败的回调函数,也可以使用catch捕获失败,then和catch最终返回的也是一个Promise,所以可以链式调用。

var p1 = new Promise(function (resolve, reject) {
  var a = Math.random() * 10;
  console.log("a=", a);
  if (a >= 5) {
    resolve("p1 resolve!:a>=5");
  } else {
    reject("p1 reject!:a<5");
  }
});

p1.then((resolve) => {
  console.log("resolve成功的结果:", resolve);
}).catch((err) => {
  console.log("reject失败的原因:", err);
});

Promise的静态方法

  • Promise.resolve() :返回的Promise对象状态为fulfilled,并且将该value传递给then方法.
  • Promise.reject():返回一个状态为失败的Promise对象,并将给定的失败信息传递给catch方法。
  • Promise.all():返回一个新的promise对象,该promise对象在参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。
  • Promise.allsettle()方法返回一个promise,该promise在所有给定的promise已被解析或被拒绝后解析,并且每个对象都描述每个promise的结果。
  • Promise.any():接收一个Promise对象的集合,当其中的一个 promise 成功,就返回那个成功的promise的值。
  • Promise.race():当参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。
  • // 与Promise.all一样,参数是一组包含Promise实例的数组,返回值是一个新的Promise实例,其实例在调用then方法中的回调函数的参数仍是一个数组。不同之处在于无论参数实例resolve还是reject,Promise.allSettled都会执行then方法的第一个回调函数
    
    // 由于单一 Promise 进入 rejected 状态便会立即让 Promise.all() 的结果进入 rejected 状态,以至于通过 Promise.all() 进入 rejected 状态时,其中的源 Promise 仍然可能处于 pending 状态,以至于无法获得所有 Promise 完成的时机。
    // Promise.allSettled() 静态方法会等待所有源 Promise 进入 fulfilled 或者 rejected 状态,从而确保不会造成时序上的冲突
    var p1 = new Promise(function (resolve, reject) {
      setTimeout(function () {
        resolve("p1 resolve!");
      }, 2000);
    });
    
    var p2 = new Promise(function (resolve, reject) {
      setTimeout(() => {
        reject("p2 reject!");
      }, 3000);
    });
    
    var p3 = Promise.resolve("p3 resolve!");
    var p4 = Promise.reject("p4 reject!");
    
    Promise.all([p1, p2, p3])
      .then((res) => {
        console.log("all成功返回:",res);
      })
      .catch((err) => {
        console.log("all失败返回:",err);
      });
    // Promse.race 就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。
    Promise.race([p1, p2, p3]).then((res) => {
      console.log("race返回:",res);
    });
    
    Promise.any([ p1,p2, p4])
      .then((res) => {
        console.log("any成功返回:",res);
      })
      .catch((err) => {
        console.log("any失败返回:",err);
      });
    // 使用async函数可以让代码简洁很多,不需要像Promise一样需要then,不需要写匿名函数处理Promise的resolve的值,也不需要定义多余的data变量,还避免了嵌套代码。
    async function f() {
      res = await Promise.allSettled([p1, p2, p3, p4]);
      console.log("res==",typeof res,res);
      const successPromise = res.filter((p) => p.status === "fulfilled");
      console.log("成功的promise:", successPromise);
    }
    f();
    
    

    17.async和await

async、await从字面上理解,async异步,await等待,async用于申明一个function是异步的,而await用于等待一个异步方法执行完成,await是同步写法,但本质还是异步调用

  • async就是一个async函数,封装了promise,而await只能在这个函数中使
  • await表示这里等待await后面的操作执行完毕,再执行下一句代码,
  • await相当于promise的then,处理promise成功
  • await 后面跟 Promise 对象:会阻断后续代码,等待状态变为 fulfilled ,才获取结果并继续执行
  • await 后续跟非 Promise 对象:会直接返回
  • try ...catch处理promise失败。

async和await的优点

  • 解决了回调地狱的问题
  • 支持并发执行
  • 可以添加返回值 return xxx
  • 可以在代码中添加try/catch捕获错误

await后面一般接什么?await 命令后面是一个 Promise 对象,它也可以跟其他值,如字符串,布尔值,数值以及普通函数

使用await处理多个异步任务时怎么并行?

(1)先生成promise,然后再调用,就会并行执行await以后的语句;

(2)使用Promise.all来调用

js多个await语句并行调用方法 | 码农家园

18.async/await 和 Promise 的关系

async/await 是消灭异步回调的终极武器。但和 Promise 并不互斥,反而,两者相辅相成。执行 async 函数,返回的一定是 Promise 对象。await 相当于 Promise 的 then。try…catch 可捕获异常,代替了 Promise 的 catch

19.深拷贝与浅拷贝

浅拷贝 :只复制了该复杂数据存储在栈内存中的地址(引用),而不是在内存中重新开辟一个新的存储空间用于存储新的对象新旧对象还是共用一个内存块.

浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址,浅拷贝基本类型之前互不影响,引用类型其中一个对象改变了地址,就会影响另一个对象。相当于只拷贝了一层

Object.assign(),展开运算符...,concat(),slice()也属于浅拷贝

let obj = { name: "maidu_xbd", action: { say: "hi" } };
let obj1 = Object.assign({}, obj); //把obj复制给{}中
obj1.name = "tom";
obj1.action.say = "你好";
console.log("obj", obj); //obj { name: 'maidu_xbd', action: { say: '你好' } }
console.log("obj1", obj1); //obj1 { name: 'tom', action: { say: '你好' } }

let obj2 = { ...obj };
obj2.name = "buding";
obj2.action.say = "hello";
console.log("obj", obj); //obj { name: 'maidu_xbd', action: { say: 'hello' } }
console.log("obj2", obj2); //obj2 { name: 'buding', action: { say: 'hello' } }

深拷贝:是新建一个一模一样的对象,该对象与原对象不共享内存,修改新对象也不会影响原对象

JSON.parse(JSON.stringify()), jQuery.extend()

let obj = { name: "maidu_xbd", action: { say: "hi" } };
let obj3 = JSON.parse(JSON.stringify(obj));
obj3.name = "buding";
obj3.action.say = "hello";
console.log("obj", obj); //obj { name: 'maidu_xbd', action: { say: 'hi' } }
console.log("obj3", obj3);//obj3 { name: 'buding', action: { say: 'hello' } }
  • 浅拷贝优点:相较于重新new一个对象,浅拷贝利用clone()方法要方便快捷许多。 效率高,内存小。
  • 浅拷贝缺点:拷贝的程度低,对于对象的各种引用无法进行拷贝。
  • 深拷贝优点:可靠性高,并且数据在处理的时候不必担心某些不安全问题。
  • 深拷贝缺点:深拷贝的运行速度较慢,效率低。开辟内存空间拷贝每一个节点身上的数据,浪费性能,开销相对更大。

20.防抖和节流

防抖:

像鼠标缩放监听,输入框输入监听等高频发触发操作只需触发一次,需要等用户高频事件完了,再进行事件操作

防抖实现:事件触发-》开启一个定时器-》如果再次触发,则清除上一次的,重新开一个定时器-》定时到,触发操作

防抖存在的一个问题,事件会一直等到用户完成操作后一段时间再操作,如果一直操作,会一直不触发。正确思路:第一次操作触发事件,后面的操作等这次触发事件完成后再触发下一次。

节流:

某个操作希望上一次的完成后再进行下一次,或者说希望间隔一定时间触发一次。如前端向后端发送一次请求,希望后端响应请求后才能再次发送请求。

节流实现:事件触发-》操作执行-》关闭阀门-》阀门关闭,后续触发无效-》一定时间后,阀门打开-》操作可再次触发

防抖和节流相同点和不同点

  • 相同点:都是为了阻止操作高频触发,从而浪费性能
  • 不同点:防抖是多次触发只生效最后一次。适用于只需要一次触发生效的场景
  • 节流是让操作每隔一段时间才能触发一次。适用于多次触发要多次生效的场景
  • 在实现防抖和节流功能时,可以直接使用Lodash的debounce和throttle函数

Lodash防抖节流的参数

_.debounce(func, [wait=0], [options=])

参数:

  1. func (Function): 要防抖动的函数。
  2. [wait=0] (number): 需要延迟的毫秒数。
  3. [options={}] (Object): 选项对象。
  4. [options.leading=false] (boolean): 指定在延迟开始前调用,默认为false
  5. [options.maxWait] (number): 设置 func 允许被延迟的最大值。
  6. [options.trailing=true] (boolean): 指定在延迟结束后调用,默认为true
testDebounce: _.debounce(function() {
  console.log("debounce");
}, 2000, {
  leading: true,
  trailing: false})

_.throttle(func, [wait=0], [options=])

参数:

  1. func (Function): 要节流的函数。
  2. [wait=0] (number): 需要节流的毫秒。
  3. [options={}] (Object): 选项对象。
  4. [options.leading=true] (boolean): 指定调用在节流开始前,默认为true
  5. [options.trailing=true] (boolean): 指定调用在节流结束后,默认为true

21.同步和异步的区别

同步是阻塞模式,异步是非阻塞模式

同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;

异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率

22.es6新特性

let 和 const 关键字、模板字符串、箭头函数、解构赋值【const {a:a1,b,c}=form】、迭代器与for-of、 rest参数、扩展运算符【var s=[...s1,...s2]】、Promise、新的原始数据类型 Symbol、Set、Map、模块化export ,import、class等

23.es7、es8新特性

  • es7:includes, **乘方运算,

    • es8:async和 await,Object.values(obj),Object.entries(obj)

24.数组去重的方法

这9种数组去重方法,直到今天,我才彻底弄懂_数据去重方法_唯一的阿金的博客-CSDN博客

  • (1)ES5方法使用for循环,双层遍历,当内层循环的值等于外层循环的值,则将内层循环的值,使用 splice() 删除。
  • (2)使用sort()排序,比较前后相邻元素是否相同,不相同则push到新数组。
  • (3)set去重 (es6)
let arr = [1, 2, 1, 4, 5, 3, 2];
let newArr = [...new Set(arr)];
console.log(newArr);

(4)filter+indexOf(返回给定值找到的第一个索引位置)

let newArr2 = arr.filter((item, index, array) => {
  return array.indexOf(item) === index;
});
console.log(newArr2);
  • (5)reduce+includes
let newArr3 = arr.reduce((total, item, index) => {
  total.includes(item) ? total : [...total, item];
}, []);
console.log(newArr3);

25.什么原因会造成内存泄露

  • 全局变量使用不当(没有声明的变量)
  • 闭包使用不当
  • 定时器/延时器没有清理
  • 没有清理的DOM元素引用(dom清空或删除时,事件未清除)

26.浏览器和nodejs的事件循环

浏览器的Event loop是在 HTML5 中定义的规范,而 node 中则由libuv库实现

macro-task(宏任务):包括整体代码script,setTimeout,setInterval,setImmediate,I/O ,UI rendering

micro-task(微任务):Promise,object.observe,process.nextTick,MutationObserver,postMessage

EventLoop过程:①先执行全局script任务,执行完主线程执行栈空;②检查微任务队列里的所有任务,依次执行,全部执行完成;③检查宏任务,读取第一个宏任务执行(执行宏任务时可能产生新的微任务),执行每个宏任务之前都要检查微任务队列是否有任务,如果有,优先执行微任务队列。微任务会全部执行,而宏任务会一个一个来执行。微任务执行完后,再去取一个宏任务来进行

libuv库负责Node API的执行。负责各种回调函数的执行时间。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎 。

nodejs的EventLoop机制的阶段操作顺序为timers、pending callbacks、idle,prepare、poll、check、close callbacks六个阶段。

26.axios 是什么,其特点和常用语法

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。前端最流行的 ajax 请求库,react/vue 官方都推荐使用 axios 发 ajax 请求。

特点:基于 promise 的异步 ajax 请求库,支持promise所有的API

浏览器端/node 端都可以使用,浏览器中创建XMLHttpRequests

支持请求/响应拦截器,支持请求取消,可以转换请求数据和响应数据,并对响应回来的内容自动转换成 JSON类型的数据,批量发送多个请求,安全性更高,客户端支持防御 XSRF,就是让你的每个请求都带一个从cookie中拿到的key, 根据浏览器同源策略,假冒的网站是拿不到你cookie中得key的,这样,后台就可以轻松辨别出这个请求是否是用户在假冒网站上的误导输入,从而采取正确的策略。

常用语法:

  • axios(config): 通用/最本质的发任意类型请求的方式
  • axios(url[, config]): 可以只指定 url 发 get 请求
  • axios.request(config): 等同于 axios(config)
  • axios.get(url[, config]): 发 get 请求
  • axios.delete(url[, config]): 发 delete 请求
  • axios.post(url[, data, config]): 发 post 请求
  • axios.put(url[, data, config]): 发 put 请求
  • axios.defaults.xxx: 请求的默认全局配置
  • axios.interceptors.request.use(): 添加请求拦截器
  • axios.interceptors.response.use(): 添加响应拦截器
  • axios.create([config]): 创建一个新的 axios(它没有下面的功能)
  • axios.Cancel(): 用于创建取消请求的错误对象
  • axios.CancelToken(): 用于创建取消请求的 token 对象
  • axios.isCancel(): 是否是一个取消请求的错误
  • axios.all(promises): 用于批量执行多个异步请求
  • axios.spread(): 用来指定接收所有成功数据的回调函数的方法

27.事件的触发过程是怎么样的?

分为三个阶段:

(1)window往事件触发处传播,遇到注册的捕获事件会触发

(2)传播到事件触发处时触发注册的事件

(3)从事件触发处往window传播,遇到注册的冒泡事件会触发

通常我们使用addEventListener注册事件

28.普通函数和箭头函数的区别

(1)定义区别:箭头函数语法比普通函数更加简洁

普通函数使用关键字function定义。

箭头函数:如果没有参数,直接写一个();如果一个参数,可以省略();如果多个参数,逗号分割。如果函数体中只有return返回语句或者只有一句代码,return和{}可以省略。

(2)关于this指向:

普通函数:直接调用时,其指向为全局对象;方法调用时,其指向为调用该方法的对象;new 调用时,其指向为新创建的实例对象;call、apply、bind 调用时,其指向为三种方法的第一个参数。

  • 箭头函数的this指向是静态的,无论如何执行或在何处执行,箭头函数内部 this 始终指向创建时所在作用域指向的对象。call,apply,bind方法改变不了箭头函数的指向
  • (3)参数区别

    箭头函数不绑定 arguments 对象,可以使用es6...rest参数代替arguments对象,来访问箭头函数的参数列表。如果在普通函数中嵌套箭头函数,并在箭头函数中访问arguments,实际上获得的是父作用域(函数)的arguments对象

  • (4)是否能用作构造器,new一起使用

    箭头函数不能用作构造器,和 new一起用会抛出错误。

    为什么箭头函数不能用作构造器,和 new一起用会抛出错误。

    因为new的过程:1.开辟内存空间;2.this指向内存空间;3.执行构造函数;4.返回this实例。但是箭头函数没有自己的this,它的this其实是继承了父作用域中的this,所以箭头函数不能作为构造函数使用。

    (5)箭头函数没有原型,原型是undefined

    (6)箭头函数不能使用yield关键字,不能作为Generator函数

普通函数与箭头函数的区别是什么?_箭头函数与普通函数有哪些区别-CSDN博客

  • 29.不适用箭头函数的场景

  • 场景1:对象方法
  • 场景2:对象原型
  • 场景3:构造函数
  • 场景4:动态上下文的回调函数
  • 场景5:vue的生命周期和method

30.JS内存泄露如何检测?场景有哪些?

内存泄漏:当一个对象不再被使用,但是由于某种原因,它的内存没有被释放,这就是内存泄漏。

有两种垃圾回收策略:标记清除、引用计数

V8 的垃圾回收机制也是基于标记清除算法,对其做了一些优化,

  • 针对新生区采用并行回收。
  • 针对老生区采用增量标记与惰性回收

拓展:WeakMap、WeakMap的作用

  • 作用是防止内存泄露的
  • WeakMapWeakMap的应用场景想临时记录数据或关系
    • vue3中大量使用了WeakMap
  • WeakMapkey只能是对象,不能是基本类型

内存泄露的场景(Vue为例)

  • 被全局变量、函数引用,组件销毁时未清除
  • 被全局事件、定时器引用,组件销毁时未清除
  • 被自定义事件引用,组件销毁时未清除

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值