BAT大厂面试真题之web前端JS篇

web前端高级必备面试资料 最近整理了下web前端面试的资料,包含了web前端、数据结构和算法、计算机基础、版本控制工具、经验分享、视频课程和面试书籍等资料 阅读详情

说说你对闭包的认识

“请讲一下你对闭包的认识”——这道题几乎是前端面试必问的问题,今天我试着总结一下如何优雅的回答这道题

什么是闭包

一句话解释:

能够读取其他函数内部变量的函数。

稍全面的回答:

在js中变量的作用域属于函数作用域, 在函数执行完后,作用域就会被清理,内存也会随之被回收,但是由于闭包函数是建立在函数内部的子函数, 由于其可访问上级作用域,即使上级函数执行完, 作用域也不会随之销毁, 这时的子函数(也就是闭包),便拥有了访问上级作用域中变量的权限,即使上级函数执行完后作用域内的值也不会被销毁。
这里涉及到对函数作用域的认识: js变量分为全局变量和局部变量;函数内部可以直接读取全局变量,而在函数外部自然无法读取函数内的局部变量

闭包解决了什么问题
1、可以读取函数内部的变量

2、让这些变量的值始终保持在内存中。不会在函数调用后被清除

可以通过下面的代码来帮助理解上面所说的:

function addCounter() {
   let counter = 0
   const myFunction = function () {
     counter = counter + 1
     return counter
   }
   return myFunction
 }
 const increment = addCounter()
 const c1 = increment()
 const c2 = increment()
 const c3 = increment()
 console.log('increment:', c1, c2, c3);
 // increment: 1 2 3

在这段代码中increment实际上就是闭包函数myFunction, 它一共运行了三次,第一次的值是1,第二次的值是2,第三次的值是3。这证明了,函数addCounter中的局部变量counter一直保存在内存中,并没有在addCounter调用后被自动清除。

闭包的应用场景
在开发中, 其实我们随处可见闭包的身影, 大部分前端 JavaScript 代码都是“事件驱动”的,即一个事件绑定的回调方法; 发送ajax请求成功|失败的回调;setTimeout的延时回调;或者一个函数内部返回另一个匿名函数,这些都是闭包的应用。

下面是具体应用的栗子:

老掉牙的取正确值问题

  for (var i = 0; i < 10; i++) {
    setTimeout(function () {
      console.log(i) //10个10
    }, 1000)
  }

怎么取到每一次循环的正确值呢? 闭包这样用:

  for (var i = 0; i < 10; i++) {
    ((j) => {
      setTimeout(function () {
        console.log(j) //1-10
      }, 1000)
    })(i)
  }

声明了10个自执行函数,保存当时的值到内部

2.使用闭包模拟私有变量

私有变量在java里使用private声明就可以了, 但是在js中还没有,但是我们可以使用闭包模拟实现。

  var counter = (function () {
    var privateCounter = 0;

    function changeBy(val) {
      privateCounter += val
    }
    return {
      increment: function () {
        changeBy(1)
      },
      decrement: function () {
        changeBy(-1)
      },
      value: function () {
        return privateCounter
      }
    }
  })();
  counter.value() //0
  counter.increment() //1
  counter.increment() //2
  counter.decrement() //1

匿名函数已经定义就立即执行, 创建出一个词法环境包含counter.increment、counter.decrement、counter.value三个方法,还包含了两个私有项:privateCounter变量和changeBy函数。这两个私有项无法在匿名函数外部直接访问,必须通过匿名包装器返回的对象的三个公共函数访问。

闭包的缺点
由于闭包会是的函数中的变量都被保存到内存中,滥用闭包很容易造成内存消耗过大,导致网页性能问题。解决方法是在退出函数之前,将不再使用的局部变量全部删除。

闭包可以使得函数内部的值可以在函数外部进行修改。所有,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

跨域问题有哪些处理方式

跨域解决方案
1、通过jsonp跨域

2、跨域资源共享(CORS)

3、nodejs中间件代理跨域

4、nginx反向代理中设置proxy_cookie_domain

Ⅰ.通过jsonp跨域
通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。

  1. 原生实现
 <script>
  var script = document.createElement('script');
  script.type = 'text/javascript';

  // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
  script.src = 'http://www.daxihong.com:8080/login?user=admin&callback=jsonCallback';
  document.head.appendChild(script);

  // 回调执行函数
  function jsonCallback(res) {
      alert(JSON.stringify(res));
  }
 </script>

服务器端返回如下(返回即执行全局函数)

jsonCallback({"status": 0, "user": "admin"})
  1. jquery方式实现
$.ajax({
  url: 'http://www.domain2.com:8080/login',
  type: 'get',
  dataType: 'jsonp',  // 请求方式为jsonp
  jsonpCallback: "handleCallback",    // 自定义回调函数名
  data: {}
});

Ⅱ.跨域资源共享(CORS)
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)跨域资源共享 CORS 详解。看名字就知道这是处理跨域问题的标准做法。CORS有两种请求,简单请求和非简单请求。

  • 简单请求

只要同时满足以下两大条件,就属于简单请求:

1、请求方法是以下三种方法之一:

  • HEAD
  • GET
  • POST

2、HTTP请求头的信息不超出以下几种字段:

  • Accept

  • Accept-Language

  • Content-Language

  • Last-Event-ID

  • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

如果是简单请求, 后端处理即可, 前端什么也不用干; 这里注意的是如果前端要带cookie, 前端也需要单独设置

  • 原生ajax (前端)
var xhr = new XMLHttpRequest();
// 前端设置是否带cookie
xhr.withCredentials = true;
...
  • jquery (前端)
$.ajax({
  ...
 xhrFields: {
     withCredentials: true    // 前端设置是否带cookie
 },
 crossDomain: true,   // 会让请求头中包含跨域的额外信息,但不会含cookie
  ...
});
  • vue中使用axios (前端)

axios.defaults.withCredentials = true

  • 后端node

可以借助koa2-cors快速实现

const path = require('path')
const Koa = require('koa')
const koaStatic = require('koa-static')
const bodyParser = require('koa-bodyparser')
const router = require('./router')
const cors = require('koa2-cors')
const app = new Koa()
const port = 9871

...
// 处理cors
app.use(cors({
  origin: function (ctx) {
    return 'http://localhost:9099'
  },
  credentials: true,
  allowMethods: ['GET', 'POST', 'DELETE'],
  allowHeaders: ['t', 'Content-Type']
}))
// 路由
app.use(router.routes()).use(router.allowedMethods())
// 监听端口
...

Ⅲ.nodejs中间件代理跨域
跨域原理: 同源策略是浏览器的安全策略, 不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议, 不会执行js脚本, 不需要检验同源策略,也就不存在跨域问题。

实现思路:通过起一个代理服务器, 实现数据的转发,也可以通过设置cookieDomainRewrite参数修改响应头cookie中域名,实现当前域下cookie的写入

  • 在vue框架下实现跨域

利用node + webpack + webpack-dev-server代理接口跨域。在开发环境下,由于vue渲染服务和接口代理服务都是webpack-dev-server同一个,所以页面与代理接口之间不再跨域,无须设置headers跨域信息了。后台可以不做任何处理。

webpack.config.js部分配置

module.exports = {
  entry: {},
  module: {},
  ...
  devServer: {
      historyApiFallback: true,
      proxy: [{
          context: '/login',
          target: 'http://www.daxihong.com:8080',  // 代理跨域目标接口
          changeOrigin: true,
          secure: false,  // 当代理某些https服务报错时用
          cookieDomainRewrite: 'www.daxihong.com'  // 可以为false,表示不修改
      }],
      noInfo: true
  }
}

Ⅳ.nginx反向代理中设置
和使用node中间件跨域原理相似。前端和后端都不需要写额外的代码来处理, 只需要配置一下Ngnix

server{
  # 监听9099端口
  listen 9099;
  # 域名是localhost
  server_name localhost;
  #凡是localhost:9099/api这个样子的,都转发到真正的服务端地址http://localhost:9871 
  location ^~ /api {
      proxy_pass http://localhost:9871;
  }    
}

对于跨域还有挺多方式可以实现, 这里就不一一列举了。

for…in 和 for…of的区别

1、for…of 是ES6新引入的特性,修复了ES5引入的for…in的不足

2、for…in 循环出的是key,for…of循环出的是value

3、for…of不能循环普通的对象,需要通过和Object.keys()搭配使用

4、推荐在循环对象属性的时候,使用for…in,在遍历数组的时候的时候使用for…of

new一个对象,这个过程中发生了什么

var obj = new Object("name","sansan");
  1. 创建一个新对象,如:var obj = {};
  2. 新对象的_proto_属性指向构造函数的原型对象。
  3. 将构造函数的作用域赋值给新对象。(也所以this对象指向新对象)
  4. 执行构造函数内部的代码,将属性添加给obj中的this对象。
  5. 返回新对象obj。

js的防抖和节流是什么

  • 防抖: 在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。

使用场景:

  1. 给按钮加函数防抖防止表单多次提交。
  2. 对于输入框连续输入进行AJAX验证时,用函数防抖能有效减少请求次数。

简单的防抖(debounce)代码:

  function debounce(fn, wait) {
    var timeout = null;
    return function () {
      if (timeout !== null) clearTimeout(timeout)
      timeout = setTimeout(fn, wait)
    }
  }
  // 处理函数
  function handle() {
    console.log(Math.random())
  }
  //滚动事件
  window.addEventListener('scroll', debounce(handle, 2000));
  • 节流: 就是指连续触发事件但是在 n 秒中只执行一次函数。节流会稀释函数的执行频率。
function throttle(func, delay) {
    var prev = Date.now();
    return function () {
      var context = this;
      var args = arguments;
      var now = Date.now();
      if (now - prev >= delay) {
        func.apply(context, args);
        prev = Date.now();
      }
    }
  }

  function handle() {
    console.log(Math.random());
  }
  window.addEventListener('scroll', throttle(handle, 2000));

区别:

函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。

数组中常用的方法有哪些

开发中数组的使用场景非常多, 这里就简单整理总结一些常用的方法;从改变原有数据的方法、不改变原有数组的方法以及数据遍历的方法三方面总结。

  • 改变原有数组的方法: (9个)
    1、splice() 添加/删除数组元素
let a = [1, 2, 3, 4, 5, 6, 7];
let item = a.splice(0, 3); // [1,2,3]
console.log(a); // [4,5,6,7]
// 从数组下标0开始,删除3个元素
let item1 = a.splice(0,3,'添加'); // [4,5,6]
console.log(a); // ['添加',7]
// 从数组下标0开始,删除3个元素,并添加元素'添加'

2、 sort() 数组排序

 var array =  [10, 1, 3, 4,20,4,25,8];
 // 升序 a-b < 0   a将排到b的前面,按照a的大小来排序的 
 array.sort(function(a,b){
   return a-b;
 });
 console.log(array); // [1,3,4,4,8,10,20,25];
 // 降序 
 array.sort(function(a,b){
   return b-a;
 });
 console.log(array); // [25,20,10,8,4,4,3,1];

3、pop() 删除一个数组中的最后的一个元素

4、shift() 删除数组的第一个元素

5、push() 向数组的末尾添加元素

6、unshift()向数组开头添加元素

7、reverse()

  let  a =  [1,2,3];
  a.pop();  // 3, 返回被删除的元素
  console.log(a); // [1,2]
  a.shift(); // 1
  console.log(a); // [2]
  a.push("末尾添加");  // 2 ,返回数组长度
  console.log(a) ; [2,"末尾添加"]
  a.unshift("开头添加"); // 3
  console.log(a); //["开头添加", 2, "末尾添加"]
  a.reverse();   // ["末尾添加", 2, "开头添加"]
  console.log(a) // ["末尾添加", 2, "开头添加"]  

8、ES6: copyWithin() 指定位置的成员复制到其他位置

let a = ['zhang', 'wang', 'zhou', 'wu', 'zheng'];
 // 1位置开始被替换, 2位置开始读取要替换的  5位置前面停止替换
 a.copyWithin(1, 2, 5);
 // ["zhang", "zhou", "wu", "zheng", "zheng"]

9、ES6: fill() 填充数组

['a', 'b', 'c'].fill(7)
// [7, 7, 7]
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']

以上是9种会改变原数组的方法, 接下来是6种常用的不会改变原数组的方法

  • 不改变原数组的方法(6种)

1、join() 数组转字符串

 let a= ['hello','world'];
 let str2=a.join('+'); // 'hello+world'

2、cancat 合并两个或多个数组

  let a = [1, 2, 3];
  let b = [4, 5, 6];
  //连接两个数组
  let newVal=a.concat(b); // [1,2,3,4,5,6]

3、ES6扩展运算符…合并数组

 let a = [2, 3, 4, 5]
 let b = [ 4,...a, 4, 4]
 console.log(a,b); 
 //[2, 3, 4, 5] [4,2,3,4,5,4,4]

4、indexOf() 查找数组是否存在某个元素,返回下标

let a=['啦啦',2,4,24,NaN]
console.log(a.indexOf('啦'));  // -1 
console.log(a.indexOf('啦啦')); // 0

5、ES7 includes() 查找数组是否包含某个元素 返回布尔

indexOf方法不能识别NaN

indexOf方法检查是否包含某个值不够语义化,需要判断是否不等于-1,表达不够直观

 let a=['OB','Koro1',1,NaN];
 a.includes(NaN); // true 识别NaN
 a.includes('Koro1',100); // false 超过数组长度 不搜索
 a.includes('Koro1',-3);  // true 从倒数第三个元素开始搜索 

6、slice() 浅拷贝数组的元素

字符串也有一个slice() 方法是用来提取字符串的,不要弄混了。

 let a = [{name: 'OBKoro1'}, {name: 'zhangsan'}];
 let b = a.slice(0,1);
 console.log(b, a); 
 // [{"name":"OBKoro1"}]  [{"name":"OBKoro1"}]
 a[0].name='改变原数组';
 console.log(b,a); 
 // [{"name":"改变原数组"}] [{"name":"改变原数组"}]
  • 遍历方法

    1. forEach:按升序为数组中含有效值的每一项执行一次回调函数。

1.无法中途退出循环,只能用return退出本次回调,进行下一次回调.
2.它总是返回 undefined值,即使你return了一个值。

  1. every 检测数组所有元素是否都符合判断条件

如果数组中检测到有一个元素不满足, 则整个表达式返回false,且元素不会再进行检测

function isBigEnough(element, index, array) { 
  return element >= 10; // 判断数组中的所有元素是否都大于10
}
[12, 5, 8, 130, 44].every(isBigEnough);   // false
[12, 54, 18, 130, 44].every(isBigEnough); // true
// 接受箭头函数写法 
[12, 5, 8, 130, 44].every(x => x >= 10); // false
[12, 54, 18, 130, 44].every(x => x >= 10); // true
  1. some 数组中的是否有满足判断条件的元素

如果有一个元素满足条件,则表达式返回true, 剩余的元素不会再执行检测

4、filter 过滤原始数组,返回新数组

5、map 对数组中的每个元素进行处理,返回新的数组

6、reduce 为数组提供累加器,合并为一个值

reduce() 方法对累加器和数组中的每个元素(从左到右)应用一个函数,最终合并为一个值。

// 数组求和 let sum = [0, 1, 2, 3].reduce(function (a, b) { return a +
b; }, 0); // 6 // 将二维数组转化为一维 将数组元素展开 let flattened = [[0, 1], [2, 3],
[4, 5]].reduce( (a, b) => a.concat(b), [] ); // [0, 1, 2, 3, 4, 5]

  1. ES6:find()& findIndex() 根据条件找到数组成员

这两个方法都可以识别NaN,弥补了indexOf的不足.

[1, 4, -5, 10,NaN].find((n) => Object.is(NaN, n)); 
// 返回元素NaN
[1, 4, -5, 10].findIndex((n) => n < 0); 
// 返回索引2
  1. ES6 keys()&values()&entries() 遍历键名、遍历键值、遍历键名+键值
for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
// 0
// 1    
for (let elem of ['a', 'b'].values()) {
  console.log(elem);
}
// 'a'
// 'b'    
for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
// 0 "a"
// 1 "b"

怎么判断一个object是否是数组

  • 方法一

使用 Object.prototype.toString 来判断是否是数组

function isArray(obj){
 return Object.prototype.toString.call( obj ) === '[object Array]';
}

这里使用call来使 toString 中 this 指向 obj。进而完成判断

  • 方法二

使用 原型链 来完成判断

function isArray(obj){
 return obj.__proto__ === Array.prototype;
}

基本思想: 实例如果是某个构造函数构造出来的那么 它的__proto__是指向构造函数的 prototype属性

方法三

利用JQuery, 利用JQuery isArray 的实现其实就是方法1。

function isArray(obj){
  return $.isArray(obj)
}

继承有哪些方式

  • ES6中的class继承

  • 原型继承

  • 构造继承

  • 寄生组合式继承

  • 实例继承

简单介绍一下前两种方式, 后面几种继承方式大家可以自行上网查找.

1、ES6中的class继承

class Animal {
  constructor(name) {
    this.name = name; 
  };
  eat() {
    console.log(this.name + '正在吃东西');
  };
}
//继承动物类
class Cat extends Animal {
 catchMouse(){
  console.log(`${this.name}正在捉老鼠`);
  }
}
var cat= new Cat('Tom猫');
cat.catchMouse();// Tom猫正在捉老鼠

细心的同学可能会发现, 在Cat 类中没有构造函数, 这里有一个小的知识点,就是ES6的继承方法中如果子类没有写构造函数的话就一般默认添加构造。举个例子。

class Cat extends Animal{
}
// 等同于
class Cat extends Animal{
  constructor(name) {
    super(name);
    //super作为函数调用时,代表父类的构造函数。
  }
}

注意:如果我写了构造函数但是没有写super的话,或者super方法的参数不对等等,编译器都会报错。

2、原型继承

在ES6之前,也有很多继承的方法,其中一个很常用的方法就是使用原型继承。其基本方法就是一个父类的实例赋值给子类的原型。这个继承方式是通过__proto__建立和子类之间的原型链,当子类的实例需要使用父类的属性和方法的时候,可以通过__proto__一级级向上找;

function Animal(name) {
  this.name = name; 
}

Animal.prototype.eat= function () {
  console.log(this.name + '正在吃东西')
};
function Cat(furColor){ 
   this.furColor = furColor ;
};
Cat.prototype = new Animal();
let tom = new Cat('black');
console.log(tom)

缺点: 1. 子类实例时,无法向父类构造函数传参。 2. 父类的私有属性被所有实例共享

**

call、apply、bind之间的关系

**

这又是一个面试经典问题, 也是ES5中众多坑中的一个,在 ES6 中可能会极大避免 this
产生的错误,但是为了一些老代码的维护,最好还是了解一下 this 的指向和 call、apply、bind 三者的区别.

bind,apply,call三者都可以用来改变this的指向, 下面分别对他们进行比较分析:

apply 和 call

  • 二者都是Function对象的方法, 每个函数都能调用

  • 二者的第一个参数都是你要指定的执行上下文

  • apply 和 call 的区别是: call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。

 var a ={
  name : "Cherry",
  fn : function (a,b) {
    console.log( a + b)
   }
}
var b = a.fn;
b.apply(a,[1,2])     // 3
b.call(a, 4,5,6)    // 15

我们常常使用的验证是否是数组(前提是toString()方法没有被重写过):

function isArray(obj){ 
  return Object.prototype.toString.call(obj) === '[object Array]' ;
}

bind 与 apply、call区别

var a ={
        name : "Cherry",
        fn : function (a,b) {
            console.log( a + b)
        }
    }
    var b = a.fn;
    b.bind(a,1,2)(); // 3

我们发现bind()方法还需要调用一次; 是由于 bind()方法创建一个新的函数,我们必须手动去调用。

bind,apply,call的共同和不同点:

  • 三者都可以用来改变this的指向

  • 三者第一个参数都是this要指向的对象,也就是想指定的上下文,上下文就是指调用函数的那个对象。(点前的那个对象,没有就是全局window)

  • 三者都可以传参,但是apply是数组,而call是有顺序的传入

  • bind 是返回对应函数,便于稍后调用;apply 、call 则是立即执行

Promise

前端面试过程中,基本都会问到 Promise,如果你足够幸运,面试官问的比较浅,仅仅问 Promise
的使用方式,那么恭喜你。事实上,大多数人并没有那么幸运, 很多面试官在promise这块都是由浅入深的提问.

  • 了解Promise吗?

  • Promise 解决了什么问题?

  • Promise 如何使用?

  • Promise 常用的方法有哪些?它们的作用是什么?

  • Promise 在事件循环中的执行过程是怎样的?

1. 了解Promise吗?
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理,让开发者不用再关注于时序和底层的结果。Promise的状态具有不受外界影响和不可逆两个特点。

2.Promise 解决了什么问题?
Promise解决了回调地狱的问题, 提高代码的可读性以及解决信任度问题. 传统的回调有五大信任问题:

调用回调过早

调用回调过晚(或者没有被调用)

调用回调次数过多或过少

未能传递所需的环境和参数

涂掉可能出现的错误和异常

3. Promise 如何使用?
ES6规定,Promise对象是一个构造函数,用来生成Promise实例。 下面代码创造了一个Promise实例。

var promise = new Promise(function(resolve, reject) {
  // ... some code

  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});

Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由JavaScript引擎提供,不用自己部署。

resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。

4. Promise 常用的方法有哪些?它们的作用是什么?

  • Promise.prototype.then

Promise 实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。它的作用是为 Promise 实例添加状态改变时的回调函数。then方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。

  • Promise.prototype.catch

Promise.prototype.catch方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。

getJSON('/posts.json').then(function(posts) {
  // ...
}).catch(function(error) {
  // 处理 getJSON 和 前一个回调函数运行时发生的错误
  console.log('发生错误!', error);
});

上面代码中,getJSON方法返回一个 Promise 对象,如果该对象状态变为resolved,则会调用then方法指定的回调函数;如果异步操作抛出错误,状态就会变为rejected,就会调用catch方法指定的回调函数,处理这个错误。

  • Promise.all

Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例, 返回最先执行结束的 Promise 任务的结果,不管这个 Promise 结果是成功还是失败。

  • Promise.race

Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。如果全部成功执行,则以数组的方式返回所有 Promise 任务的执行结果。 如果有一个 Promise 任务 rejected,则只返回 rejected 任务的结果。

  1. Promise 在事件循环中的执行过程是怎样的
var promise = new Promise((resolve, reject)=>{
     console.log('我是promise任务');
     resolve('resolved')
   })
   promise.then(res =>{
     console.log(res)
   })
   console.log("我是同步任务");
   setTimeout(()=>{
     console.log("我是延时任务");
   }, 0)

上面代码的执行顺序是: 我是promise任务、我是同步任务、resolved、我是延时任务。

Promise 新建后立即执行,立即 resolve 的 Promise 对象,是在本轮“事件循环”(event loop)的结束时,而不是在下一轮“事件循环”的开始时;setTimeout在下一轮“事件循环”开始时执行。

总结
在面试中, 很多问题并没有真正的答案,至于知识点能掌握到什么样的程度,都需要靠自己不断的学习积累, 在开发中不断的使用也是加深对知识点理解的方式。由于个人精力有限,只是针对一些常遇到的面试题,做了一些浅显的答案解析,希望对大家有所帮助吧,大家也可以进我创的一个裙:619596o65,里面有众多小伙伴在一起交流学习,快点加入吧~

利用SpringBoot和Vue实现前后端分离(附源码),BAT大厂前端面试真题锦集干货整理 el-button type=“primary” @click=“submitForm(‘ruleForm2’)”>提交。©kak.com 京ICP证XXXXX号,本网站所列数据,除特殊说明,所有数据均出自我司实验室测试。引用ElementUI的组件,引用axios并设置基础的url。@CrossOrigin //标识接受跨域处理。在resources/mapping下编写。//引用axios,设置基础的url。 阅读详情

相关推荐

零成本实现飞牛 OS 内网穿透:CloudFlare 隧道搭建全攻略

一、引言:突破内网限制的最优解当你的内网环境中部署了飞牛 OS 系统(无论是老旧电脑还是 NAS 设备),想要实现公网访问时,传统方案往往面临两大痛点:公网 IP 申请困难且成本高DDNS 动态解析配置复杂专业内网穿透工具存在付费门槛今天为大家带来零成本解决方案:通过免费域名搭配 CloudFlare 隧道技术,无需公网 IP 即可轻松实现飞牛 OS 服务的公网访问。全程操作可视化,新手也能快速上手!二、前期准备:必备工具清单(1)域名准备。

Honmaple的博客 7491

web前端面试都问什么-JS篇

本文中讲解的面试题说说对闭包的认识,它解决了什么问题?跨域问题有哪些处理方式?for...in 和 for...of的区别?new一个对象, 这个过程中发生了什么?js的...

程序员成长指北 2152

手把手教你使用ESM-2进行蛋白质结构预测:从安装到实战

本文详细介绍了如何使用ESM-2蛋白质语言模型进行蛋白质结构预测,从环境准备、模型安装到实战应用。通过逐步指导,读者可以掌握ESM-2的配置、单序列预测、结果可视化及高级优化技巧,适用于生物信息学研究和药物开发。

weixin_29306875的博客 532

闭包的定义,闭包是什么?闭包解决了什么问题?闭包有哪些应用场景?使用闭包应该注意什么?

1、闭包是什么? 闭包是有权限访问其他函数作用域的局部变量的一个函数 这是《 JavaScript高级程序设计 》中给出的定义, 如果你想用一句话就把面试官搞定几乎是不可能的。 因为这句话还存在下面几个深入的问题: 为什么其他非闭包的函数,没有权限访问另一个函数的内部作用域 为什么闭包有这个权限 什么是函数作用域 面试官更想知道的是你是否知道上面的内容 更周全的解释方法: 由于在JS中,变量的作用域属于函数作用域,在函数执行后作用域就会被清理、内存也随之被收回,但是由于闭包是建立在一个函数内部的子函

qq_36560875的博客 4436

WIFI中CSI的读取

学习目标: 目前正在做基于WIFI的无设备定位,准备使用信道状态信息(CSI),学习一下。 目前采集数据环境已经搭建好,准备研究信号的预处理。 学习内容: 1、 信号的读取——read_bf_file函数的研究 2、 3、 4、 1. read_bf_file详解: %READ_BF_FILE Reads in a file of beamforming feedback logs. % This version uses the *C* version of read_bfee, ...

sz3076799的博客 8892

语义分割系列7-Attention Unet(pytorch实现)

本文介绍了AttentionUnet模型和其主要中心思想,并在pytorch框架上构建了Attention Unet模型,构建了Attention gate模块,在数据集Camvid上进行复现。

yumaomi的博客 2万+

web 前端面试题50道

整理出来web前端面试比较常见的50道题

Liumxe的博客 1万+

GAN管CGH40010F设计宽带Doherty功放:如何用ADS搞定输入匹配、合路网络与功分器?

本文详细介绍了基于CGH40010F GaN晶体管的宽带Doherty功放设计流程,重点讲解在ADS平台中实现输入匹配网络、合路网络与功分器的关键技术。通过寄生参数补偿、渐变微带线设计和复合补偿结构等方法,解决了宽带化设计中的核心挑战,最终实现1.7-2.6GHz频段内72%的峰值效率和52%的回退效率。

weixin_42614269的博客 473

Web前端面试题(附答案及解析)(2026年最新版)

【Web 前端面试必备】精选高频面试题 + 详细答案解析,搭配实战总结心得,帮你高效复盘考点、轻松应对面试! 内容会持续更新,你的每一份支持都是我更新的动力,感谢关注!

这世上从不缺让人上头的新鲜感,能顾及你情绪的人实属难得。 37万+

PE启动盘结合360杀毒离线版:深度清除顽固病毒实战指南

在系统安全维护领域,离线查杀是一种在独立于宿主操作系统的环境下进行病毒扫描和清除的核心技术。其原理是通过一个预启动环境(如PE)加载杀毒软件,从而绕过可能已被感染或受保护的系统核心,直接访问和扫描磁盘文件。这项技术的核心价值在于能够彻底处理那些在正常系统运行时难以清除的深度隐藏病毒、Rootkit和驱动级木马。典型的应用场景包括应对勒索软件、顽固感染型病毒以及系统启动项被劫持等情况。本文以“PE启动盘”和“360杀毒离线版”这一经典组合为例,详细解析了从工具选型、环境部署到深度查杀策略的全流程,为系统维护人

weixin_29741447的博客 408

【Clickhouse】Cannot allocate block number in Zookeeper write prefix view location

我有一个问题,我CK集群跑批的时候,replicated表变成只读的了下面是CK的报错和当时ZK的日志。下面是zk报错开始 我认为是写入的时候,压力太大,ZK扛不住了,就按照博客里的建议优化了ZK的参数,现在偶尔还会只读,zk报错都是图里的那种clickhouse的集群是5分片的集群,数据量比较大。每小时批量一次,每次2-10W条数据,字段的话,不到200个字段,使用的 jdbc sink写入。

九师兄 836

常见的前端面试题【90道】

1、vue的基本原理2、说说你对盒子模型的理解?3、说说javascript都有哪些数据类型,如何存储的?4、如何理解响应式,实现响应式的方法有哪些?有什么区别?5、Css性能优化有哪些常见的方法?具体如何实现?6、判断数据类型的方法有哪些?有什么区别?7、说说你对事件循环的理解?8、说说你对BOM的理解,BOM的核心都有哪些?作用是什么9、Bind,call,apply有什么区别?如何实现一个bind方法?10、如何理解闭包?闭包的应用场景是?11、说说你对同步和异步的区别的理解?

qq_50294652的博客 2万+

基于STM32F1XX 、HAL库的OPT4001-Q1环境光传感器驱动应用C语言程序设计

OPT4001-Q1 的输出是半对数 的,具有 9 个二进制对数满量程照度范围,每个范围内具有高度线性响应,使得 PicoStar™ 型号的测量能力为 312.5μlux 至 84klux,USON 型号的测量能力为 400µlux 至 107klux。// 禁用中断(示例)

PP_Cottage的博客 461

web前端进阶大厂面试资料合集

最近整理了下web前端面试的资料,包含了web前端、数据结构和算法、计算机基础、版本控制工具、经验分享、视频课程和面试书籍等资料,还有比这更全的没有? 废话不多说,直接上干货,欢迎收藏,不用客气。 前端 面试官求你别再问我hook了 前端开发技术面试指南及真题讲解带你入坑BAT 一线大厂前端面试题年末大汇总 web企业面试题精讲 2年前端(外包经历) 6月部分面试记录 (高级、资深岗位) 三十七个常见Vue面试题,背就完事了 看过 100 份前端简历之后,汇总一下常见的问题 2021

m0_67537062的博客 1714

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

前端面试资料集合

内容包括JavaScript、CSS、HTML及框架知识,书中同时提供了大量的笔试题和面试题解析,帮助读者掌握扎实的技术基础并在面试中脱颖而出。课程涵盖常用的数据结构(如数组、链表、堆、树等)和算法(排序、查找、递归等),通过理论讲解和实际编程练习,帮助学员深入理解和掌握这些重要的计算机科学基础知识。通过对题目的详细解析,学员可以掌握Web技术的核心概念以及面试中可能遇到的实际问题,帮助他们在面试中表现得更为出色。27、说下你的Vue项目的目录结构,如果是大型项目你该怎么划分结构和划分组件呢?

2401_86900447的博客 4439

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

怎么学好web前端,7 Web前端性能优化,BAT大厂前端面试真题锦集干货整理

更新10个图标文件,不宜把10个文件一次全部更新,而是应一个文件一个文件逐步更新,并有一定的间隔时间,以免用户浏览器突然大量缓存失效,集中更新缓存,造成服务器负载骤增、网络堵塞的情况。在服务器端对文件进行压缩,在浏览器端对文件解压缩,可有效减少通信传输的数据量。文本文件的压缩效率可达80%以上,因此HTML、CSS、JavaScript文件启用GZip压缩可达到较好的效果。但是压缩对服务器和浏览器产生一定的压力,在通信带宽良好,而服务器资源不足的情况下要权衡考虑。

2401_83739821的博客 763

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

最火大厂面试题、面试技巧汇总及简历编写(附简历模版下载)

最近有粉丝反馈金三银四已到,准备跳槽或整体提升一下技术,有没有一些优秀的大厂面经、面试题、简历编写技巧、简历模版等资料,所以本文就统一整理一些瓶子君所知道的面试资料。大佬们的面试历程一位前...

我本可以容忍阳光,如果我不曾见过太阳,然而阳光已使我荒凉,成为更新的荒凉。 2067

【金三银四】关于Web前端开发中常见的经典算法题 阿里、字节跳动真题

引言 金三银四,特地整理一份面试题,现介绍本文特色: 1、适合前端,需要面试找工作 2、即将毕业面临实习,积累经验 3、从务实基础到彻底弄懂 4、探索框架源码,研究前端必备算法 5、直击阿里、腾讯、美团、今日头条等大厂原题,逐步引入 6、学完即准备投简历 BAT/TMD这样的大公司是如何面试的 注意嗷,在这里TMD可不是骂人的话哦,可能你知道BAT,但TMD你知道么?(不知道赶紧去百度!) ...

超逸の学习技术博客 2483

2024年前端最全vue 中router-link属性设置(1),2024年最新BAT大厂前端面试真题锦集干货整理

从转行到现在,差不多两年的时间,虽不能和大佬相比,但也是学了很多东西。我个人在学习的过程中,习惯简单做做笔记,方便自己复习的时候能够快速理解,现在将自己的笔记分享出来,和大家共同学习。开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】个人将这段时间所学的知识,分为三个阶段:第一阶段:HTML&CSS&JavaScript基础第二阶段:移动端开发技术第三阶段:前端常用框架推荐学习方式:针对某个知识点,可以先简单过一下我的笔记,如果理解,那是最好,可以帮助快速解决问题;

2401_84447112的博客 937

web前端最新面试资料

web前端面试的资料,包含了web前端、数据结构和算法、计算机基础、版本控制工具、经验分享、视频课程和面试书籍等资料

the_cleaner的博客 556

2024年最全前端工程师的迷茫:不知道我这种前端是不是被淘汰了?,BAT大厂前端面试真题锦集干货整理

面试一面会问很多基础问题,而这些基础问题基本上在网上搜索,面试题都会很多很多。最好把准备一下常见的面试问题,毕竟面试也相当与一次考试,所以找工作面试的准备千万别偷懒。面试就跟考试一样的,时间长了不复习,现场表现肯定不会太好。表现的不好面试官不可能说,我猜他没发挥好,我录用他吧。开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】96道前端面试题:常用算法面试题:内容主要包括HTML,CSS,JavaScript,浏览器,性能优化前端开发很有前途,是一项不会被淘汰的技术。

2401_84411767的博客 285

BAT头条、美团、京东等各大公司前端面试题汇总,会持续更新~

- 下面是为各位小伙伴收录的包括 阿里、腾讯、百度、今日头条、美团、滴滴、京东、小米、华为、网易、新浪等各大公司的前端面试题。 - 分享给各们想换工作的小伙伴们,拿走~ 百度前端面试题(一) 百度前端工程师面试题及答案解 百度前端面试题(二) 百度前端面试题之 - 百度三面 百度前端面试之–如何成为百度offer收割机 百度前端面试题(三) 百度前端面试题(四) 百度前端面试题之–面试过程与总结...

北回归线 862

windows下使用forever守护Node,BAT等大厂必问技术面试题

开始 → 运行 → cmd,输入以下命令:卸载的命令:如果安装淘宝npm镜像,在cmd窗口执行下方命令:注意:安装完后最好查看其版本号cnpm -v或关闭命令提示符重新打开,安装完直接使用有可能会出现错误;cnpm跟npm用法完全一致,只是在执行命令时将npm改为cnpm(以下操作将以cnpm代替npm)。

2301_78416543的博客 986

2,一位前端大牛的BAT面试心得与经验总结,2024一线互联网校招面试真题解析

也就是说,事先考虑到某一变量可能取的值,尽量用自然语言中含义清楚的单词来表示它的每一个值,这种方法称为枚举方法,用这种方法定义的类型称枚举类型。最近得空把之前遇到的面试题做了一个整理,包括我本人自己去面试遇到的,还有其他人员去面试遇到的,还有网上刷到的,我都统一的整理了一下,希望对大家有用。一般来说,面试官会根据你的简历内容去提问,但是技术基础还有需要自己去准备分类,形成自己的知识体系的。号,其后的所有元素都要后缀?•第 4 行,arr[0] 是一个数字类型,没有 substr() 方法,所以报错。

imtokenmax众筹 531

React 基础:在组件之间传递数据,2024年最新BAT大厂前端面试真题锦集干货整理

请注意,我们也将其命名books为,因此将顶部数据集重命名为booksData现在我们可以添加一个按钮来onClick加载我们的书籍。

时间与思念 968
上一篇: 前端工程师是怎样一种职业?想要学习web前端的小白看过来
下一篇: 互联网的缩影——前端开发
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值