2021年这些js相关的前端面试题真的值得收藏(一)

简介: 2021年这些js相关的前端面试题真的值得收藏

1. 实用js写红绿灯的效果?

<ul id="traffic" class="">
 <li id="green"></li>
 <li id="yellow"></li>
 <li id="red"></li>
</ul>
ul {
 position: absolute;
 width: 200px;
 height: 200px;
 top: 50%;
 left: 50%;
 transform: translate(-50%,-50%);
}
 /*画3个圆代表红绿灯*/
 ul >li {
  width: 40px;
  height: 40px;
  border-radius:50%;
  opacity: 0.2;
  display: inline-block;
 }
 /*执行时改变透明度*/
 ul.red >#red, 
 ul.green >#green,
 ul.yellow >#yellow{
  opacity: 1.0;
 }
 /*红绿灯的三个颜色*/
 #red {background: red;}
 #yellow {background: yellow;}
 #green {background: green;}
function timeout(timer){
  return function(){ 
   return new Promise(function(resolve,reject){
   setTimeout(resolve,timer) 
   })  
  }
  }
 var green = timeout(3000);
 var yellow = timeout(4000);
 var red = timeout(5000);
 var traffic = document.getElementById("traffic");
 (function restart(){
  'use strict'      //严格模式
  console.log("绿灯"+new Date().getSeconds()) //绿灯执行三秒 
  traffic.className = 'green';
  green()
  .then(function(){
   console.log("黄灯"+new Date().getSeconds()) //黄灯执行四秒
   traffic.className = 'yellow';
   return yellow();
  })
  .then(function(){
   console.log("红灯"+new Date().getSeconds()) //红灯执行五秒
   traffic.className = 'red';
   return red();
  }).then(function(){
   restart()
  })
  })();

2. axios是否需要promise封装?

需要

import axios from 'axios'
const http = ({
  url,method,params,headers
}) => {
return new Promise ( (resolve,reject) => {
  axios({
    url,
    method,
    params,
    headers
  })
  .then( res => {
    resolve(res)
  })
  .catch( error => {
    throw error
  })
  })
}
export default http

3. Promise内部发生错误,如果同时.then方法有第二个参数,也有.catch会调用哪个

.catch

4. 宏任务 微任务

setTimeout(function(){
        console.log('1')
    });
    new Promise(function(resolve){
        console.log('2');
                    resolve();
    }).then(function(){
        console.log('3')
    });
    console.log('4')

settimeout肯定是异步的。 我也知道有一个event队列,你settimeout没设置时间应该直接就进入这个队列了吧,然后就是Promise的回掉函数进入event队列。 当时我二话不说给了个答案 2,4,1,3.并且很自信。然后面试官就问你不想想了?我说不想了。然后后半段他全程开始皱眉头了。我也凉凉。最后他让我回去看一下宏任务和微任务。


首先说一下普通的异步函数的执行过程吧


同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。当指定的事情完成时,Event Table会将这个函数移入Event Queue。主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。上述过程会不断重复,也就是常说的Event Loop(事件循环)。


那么如此看来我给的答案还是对的。但是js异步有一个机制,就是遇到宏任务,先执行宏任务,将宏任务放入eventqueue,然后在执行微任务,将微任务放入eventqueue最骚的是,这两个queue不是一个queue。当你往外拿的时候先从微任务里拿这个回掉函数,然后再从宏任务的queue上拿宏任务的回掉函数。 我当时看到这我就服了还有这种骚操作。


而宏任务一般是:包括整体代码script,setTimeout,setInterval。


微任务:Promise,process.nextTick。


记住就行了。


然后回到开头的代码。因为settimeout是宏任务,虽然先执行的他,但是他被放到了宏任务的eventqueue里面,然后代码继续往下检查看有没有微任务,检测到Promise的then函数把他放入了微任务序列。等到主线进程的所有代码执行结束后。先从微任务queue里拿回掉函数,然后微任务queue空了后再从宏任务的queue拿函数。


所以正确的执行结果当然是:2,4,3,1。


https://juejin.im/post/59e85eebf265da430d571f89


5. Js 原型和原型链


原型链的设计是js的精髓所在,比较抽象。需要从内部设计原理去理解这种设计思想,在纸上画画其中的关系会帮助理解。


prototype对象


prototype对象的引入:所有实例对象需要共享的属性和方法,都放在这个对象中,那些不需要共享的属性和方法,就放在构造函数中。以此来模拟类。


function Animal(name) {
    this.name = name
}
Animal.prototype.getName = function() {
    console.log(this.name)
}
var animal1 = new Animal('Kate')
var animal2 = new Animal('Lucy')
//对象animal1 和 animal2共享方法getName
animal1.getName()
animal2.getName()

原型链


在javascript中,每个对象都有一个指向它的原型(prototype)对象的内部链接。每个原型对象又有自己的原型,直到某个对象的原型为null为止,组成这条链的最后一环。


*proto写入es6标准


当一个对象被创建时,它的__protp__属性和内部属性[[prototype]]指向相同的对象(也就是它的构造函数的prototype属性)。改变__proto__属性的值同时也会改变内部属性[[prototype]]的值,除非该对象是不可扩展的。

在ES5中,所有构造函数的__proto__都指向Function.prototype

**在ES6中,构造函数的__proto__指向它的父类构造函数

obj.__proto__ === obj.[[prototype]]
// ES5
Cat.__proto__ === Function.prototype
// ES6
Cat.__proto__ === Animal

构造函数继承

有四种方式可以实现构造函数的继承

1.调用apply方法

function Animal() {
    this.species = '动物'
}
Animal.prototype.getName = function() {
    console.log('我是动物')
}
function Cat() {
    Animal.apply(this, arguments)
}
var cat = new Cat()
cat.species    // 动物
cat.getName()  // undefined

这种方法可以继承父类构造函数的属性,但是无法继承prototype属性,即父类中共享的方法和属性

2.改写prototype对象

Cat.prototype = new Animal()
Cat.prototype.constructor = Cat

这是最常用的方法来模拟单继承,缺点是始终要保留Animal的对象,如果Animal对象比较大时,会消耗部分内存(其实很少),并且没有实现多继承


3.直接继承prototype

Cat.prototype = Animal.prototype
Cat.prototype.constructor = Cat

缺点是当修改了Cat.prototype上的方法时会影响Animal.prototype

4.利用空对象作中介

var F = function(){}
F.prototype = Animal.prototype
Cat.prototype = new F()
Cat.prototype.constructor = Cat

6. js的事件循环机制是什么

进程、线程


进程是系统分配的独立资源,是 CPU 资源分配的基本单位,进程是由一个或者多个线程组成的。

线程是进程的执行流,是CPU调度和分派的基本单位,同个进程之中的多个线程之间是共享该进程的资源的。


浏览器内核


浏览器是多进程的,浏览器每一个 tab 标签都代表一个独立的进程(也不一定,因为多个空白 tab 标签会合并成一个进程),浏览器内核(浏览器渲染进程)属于浏览器多进程中的一种。


浏览器内核有多种线程在工作。


GUI 渲染线程:


负责渲染页面,解析 HTML,CSS 构成 DOM 树等,当页面重绘或者由于某种操作引起回流都会调起该线程。

和 JS 引擎线程是互斥的,当 JS 引擎线程在工作的时候,GUI 渲染线程会被挂起,GUI 更新被放入在 JS 任务队列中,等待 JS 引擎线程空闲的时候继续执行。

JS 引擎线程:


单线程工作,负责解析运行 JavaScript 脚本。

和 GUI 渲染线程互斥,JS 运行耗时过长就会导致页面阻塞。

事件触发线程:


当事件符合触发条件被触发时,该线程会把对应的事件回调函数添加到任务队列的队尾,等待 JS 引擎处理。

定时器触发线程:


浏览器定时计数器并不是由 JS 引擎计数的,阻塞会导致计时不准确。

开启定时器触发线程来计时并触发计时,计时完成后会被添加到任务队列中,等待 JS 引擎处理。

http 请求线程:


http 请求的时候会开启一条请求线程。


请求完成有结果了之后,将请求的回调函数添加到任务队列中,等待 JS 引擎处理。


JavaScript 引擎是单线程


JavaScript 引擎是单线程,也就是说每次只能执行一项任务,其他任务都得按照顺序排队等待被执行,只有当前的任务执行完成之后才会往下执行下一个任务。


HTML5 中提出了 Web-Worker API,主要是为了解决页面阻塞问题,但是并没有改变 JavaScript 是单线程的本质。了解 Web-Worker。


JavaScript 事件循环机制


JavaScript 事件循环机制分为浏览器和 Node 事件循环机制,两者的实现技术不一样,浏览器 Event Loop 是 HTML 中定义的规范,Node Event Loop 是由 libuv 库实现。这里主要讲的是浏览器部分。


Javascript 有一个 main thread 主线程和 call-stack 调用栈(执行栈),所有的任务都会被放到调用栈等待主线程执行。


JS 调用栈


JS 调用栈是一种后进先出的数据结构。当函数被调用时,会被添加到栈中的顶部,执行完成之后就从栈顶部移出该函数,直到栈内被清空。


同步任务、异步任务


JavaScript 单线程中的任务分为同步任务和异步任务。同步任务会在调用栈中按照顺序排队等待主线程执行,异步任务则会在异步有了结果后将注册的回调函数添加到任务队列(消息队列)中等待主线程空闲的时候,也就是栈内被清空的时候,被读取到栈中等待主线程执行。任务队列是先进先出的数据结构。


Event Loop


调用栈中的同步任务都执行完毕,栈内被清空了,就代表主线程空闲了,这个时候就会去任务队列中按照顺序读取一个任务放入到栈中执行。每次栈内被清空,都会去读取任务队列有没有任务,有就读取执行,一直循环读取-执行的操作,就形成了事件循环。


7.前端跨域的方式


前端跨域的方案:
1、通过jsonp跨域
2、postMessage跨域
3、跨域资源共享(CORS)
4、nginx代理跨域
5、nodejs中间件代理跨域
6、WebSocket协议跨域
7.反向代理
<u>https://segmentfault.com/a/1190000011145364</u>
相关文章
|
25天前
|
JavaScript 前端开发 程序员
前端原生Js批量修改页面元素属性的2个方法
原生 Js 的 getElementsByClassName 和 querySelectorAll 都能获取批量的页面元素,但是它们之间有些细微的差别,稍不注意,就很容易弄错!
|
22天前
|
JavaScript 前端开发 Java
springboot解决js前端跨域问题,javascript跨域问题解决
本文介绍了如何在Spring Boot项目中编写Filter过滤器以处理跨域问题,并通过一个示例展示了使用JavaScript进行跨域请求的方法。首先,在Spring Boot应用中添加一个实现了`Filter`接口的类,设置响应头允许所有来源的跨域请求。接着,通过一个简单的HTML页面和jQuery发送AJAX请求到指定URL,验证跨域请求是否成功。文中还提供了请求成功的响应数据样例及请求效果截图。
springboot解决js前端跨域问题,javascript跨域问题解决
|
25天前
|
缓存 JavaScript 前端开发
JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用
本文深入讲解了 JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用。
38 5
|
23天前
|
缓存 前端开发 JavaScript
JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式
本文深入解析了JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式(Hash路由和History路由)、优点及挑战,并通过实际案例分析,帮助开发者更好地理解和应用这一关键技术,提升用户体验。
57 1
|
27天前
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
33 4
|
1月前
|
移动开发 前端开发 JavaScript
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
于辰在大学期间带领团队参考网易游戏官网的部分游戏页面,开发了一系列前端实训作品。项目包括首页、2021校园招聘页面和明日之后游戏页面,涉及多种特效实现,如动态图片切换和人物聚合效果。作品源码已上传至CSDN,视频效果可在CSDN预览。
33 0
前端实训,刚入门,我用原生技术(H5、C3、JS、JQ)手写【网易游戏】页面特效
|
存储 缓存 JavaScript
56 道高频 JavaScript 与 ES6+ 的面试题及答案(下)
56 道高频 JavaScript 与 ES6+ 的面试题及答案(下)
387 0
56 道高频 JavaScript 与 ES6+ 的面试题及答案(下)
|
存储 缓存 JSON
56 道高频 JavaScript 与 ES6+ 的面试题及答案(中)
56 道高频 JavaScript 与 ES6+ 的面试题及答案(中)
318 0
|
存储 设计模式 缓存
14万字 | 400多道JavaScript 面试题及详细答案03(建议收藏)
14万字 | 400多道JavaScript 面试题及详细答案(建议收藏)
193 0
14万字 | 400多道JavaScript 面试题及详细答案03(建议收藏)
|
Web App开发 JavaScript 前端开发
14万字 | 400多道JavaScript 面试题及详细答案12(建议收藏)
14万字 | 400多道JavaScript 面试题及详细答案12(建议收藏)
177 0