前端js面试题目

js

- javascript 中共几种基本数据类型

七种基本数据类型:
1、六种基本数据类型
undefined,null,string,boolean,number,symbol(ES6)
2、一种引用类型
Object
 

- 基本数据类型和引用数据类型的数据内存有什么不同?

基本数据类型:是保存在栈内存当中,复制的时候是值传递。栈内存中只存放具体的地址值。
引用数据类型:是保存在堆内存当中,
 

- typeof返回的数据类型有哪些?

“typeof”可以返回的数据类型有:
“number”、“string”、“boolean”、“undefined”、“object”、“function”。
 

- ES6为什么要引入 Symbol?

ES5的对象中的属性名是字符串,容易造成属性名的冲突,如果有一种机制,保证每个属性的名字都是独一无二的,就可以从根本上防止属性名的冲突。
 

- 栈和队列的区别?

队列是先进先出,有出口和入口,先进去可以先出来。
栈就像一个箱子,后放上去的,可以先出来,先进后出。
 

- const, var, let的区别?

1、var声明的变量会挂载在window上,而let和const声明的变量不会;
2、var声明变量存在变量提升,let和const不存在变量提升,需要遵循“先声明,后使用”原则,否则会报错;
3、let和const声明形成块作用域;
4、同一作用域下let和const不能声明同名变量,而var可以;
5、暂存死区,在代码块内,使用let声明变量之前,该变量都是不可以使用;
6、const一旦声明必须赋值,不能使用null占位,声明后不能再修改,如果声明的是引用类型的数据,可以修改其属性,但是不能修改对象的地址。
 

- Object都有哪些方法?

Object.assign,Object.create,Object.keys,Object.values, Object.entries,Object.is
 

- Array都有哪些方法?

join(),push()和pop(),shift() 和 unshift(),sort(),reverse(),concat(),slice(),splice(),indexOf()和 lastIndexOf(),forEach(),map() ,filter(),every() ,some() ,reduce()和 reduceRight()

不改变原数组的有:
concat,join,slice,map,foreach,filter,some,every

- js 怎么实现深拷贝?

// 方法一
var newobj = JSON.stringify(obj),
deepclose = JSON.parse(newobj)
// 方法二 循环属性创建对象
// Object.assign为浅拷贝
let newobj1 = Object.assign({}, obj)

 

- bind,call,apply的区别?

1、三者都可以改变函数的this对象指向
2、三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefined或null,则默认指向全局window
3、三者都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入
4、bind是返回绑定this之后的函数,apply、call 则是立即执行

- ES6中常用的新特性有哪些?

1、const,let,
2、模版字符串:ES6反引号(``)直接搞定
3、箭头函数
4、操作符(…)
5、for…of 和 for…in
6、class类,就是一个原型链的表现形式
7、promise
8、async,await
 

- ES5与ES6继承的区别?

ES5
ES5的继承是先创建子类的实例, 然后再创建父类的方法添加到this上.
通过原型和构造函数机制实现的.
// ES5的继承
// 原型链方式: 子类的原型指向父类的实例
// 缺点: 1. 因为原型链继承共享实例属性,属于引用类型传值, 修改某个实例的属性会影响其他的实例

ES6
ES6的继承是先创建父类的实例对象this(必须先调用super方法), 再调用子类的构造函数修改this.

通过关键字class定义类, extends关键字实现继承. 子类必须在constructor方法中调用super方法否则创建实例报错. 因为子类没有this对象, 而是使用父类的this, 然后对其进行加工

super关键字指代父类的this, 在子类的构造函数中, 必须先调用super, 然后才能使用this
// ES6的继承
// 在子类的构造器中先调用super(), 创建出父类实例, 然后再去修改子类中的this去完善子类

摘抄:

- Class和构造函数的异同?

类的形式
可以在Class内部同时定义普通对象的属性方法,定义构造函数对象上面的方法,定义原型对象上面的方法属性
值得注意的是通过静态关键字只能在构造函数对象上面添加方法,也就是说只能定义静态的方法,不能定义静态的属性
构造函数的形式
在构造函数内部只能定义普通对象上面的方法和属性
静态方法也就是构造函数对象上面的方法,只能通过显式的追加
原型对象上面的方法和属性也需要显式的追加

  1. Class 在语法上更加贴合面向对象的写法
  2. Class在实现继承上更加易读、易理解
  3. 更易于写java等后端语言
  4. 本质还是语法糖,使用prototype

摘抄:

- TypeScript 和 JavaScript 的区别?

1、TypeScript 可以使用 JavaScript 中的所有代码和编码概念,TypeScript 是为了使 JavaScript 的开发变得更加容易而创建的。例如,TypeScript 使用类型和接口等概念来描述正在使用的数据,这使开发人员能够快速检测错误并调试应用程序
2、TypeScript 从核心语言方面和类概念的模塑方面对 JavaScript 对象模型进行扩展。
3、JavaScript 代码可以在无需任何修改的情况下与 TypeScript 一同工作,同时可以使用编译器将 TypeScript 代码转换为 JavaScript。
4、TypeScript 通过类型注解提供编译时的静态类型检查。
5、TypeScript 中的数据要求带有明确的类型,JavaScript不要求。
6、TypeScript 为函数提供了缺省参数值。
7、TypeScript 引入了 JavaScript 中没有的“类”概念。
8、TypeScript 中引入了模块的概念,可以把声明、数据、函数和类封装在模块中。
语言层面:JavaScript和TypeScript都是ECMAScript(ECMA-262)的具体实现。
执行环境层面:浏览器引擎和Node.js都能够直接运行JavaScript,但无法直接运行TypeScript。
时序层面:TypeScript被真正执行前,会通过编译转换生成JavaScript,之后才能被解释执行。
厂商层面:JavaScript由Netscape率先推出,现在主要由各大浏览器厂商实现。而TypeScript is a trademark of Microsoft Corporation,目前由微软进行设计和维护。
TypeScript是ECMAScript 2015的语法超集,是JavaScript的语法糖。JavaScript程序可以直接移植到TypeScript,TypeScript需要编译(语法转换)生成JavaScript才能被浏览器执行。

摘抄:

- JS判断数组的5种方式

let arr = []
1.  instanceof 
    arr  instanceof Array

2. __proto__
    arr.__proto__  === Array.prototype

3. constructor
    arr.constructor === Array

4. Object.prototype.toString
    Object.prototype.toString.call(arr) === '[object Array]'

5. Array.isArray
    Array.isArray(arr)

 

- js的结构赋值?

function test1({x=0, y=0} = {}) {
    console.log([x, y])
}

test1({x:1, y:2})
test1({x:1})
test1({})
test1()
// [1, 2]
// [1, 0]
// [0, 0]
// [0, 0]

function test2({x, y} = {x: 0, y:0}) {
    console.log([x, y])
}   

test2({x:1,y:2})
test2({x:1})
test2({})
test2()
// [1, 2]
// [1, undefined]
// [undefined, undefined]
// [0, 0]

 

- 闭包的优缺点

优点:
1、让局部变量不回收
2、避免全局变量的污染
缺点:
1、常驻内存,增加内存使用量。
2、内存泄露,解决方法是,在退出函数之前,将不使用的局部变量全部删除。
 

- JS原型链中的prototype和__proto__的区别?

- 什么是宏任务和微任务?

Js 是单线程的,但是一些高耗时操作带来了进程阻塞的问题。为了解决这个问题,Js 有两种任务的执行模式:同步模式(Synchronous)和异步模式(Asynchronous)。

在异步模式下,创建异步任务主要分为宏任务与微任务两种。ES6 规范中,宏任务(Macrotask) 称为 Task, 微任务(Microtask) 称为 Jobs。宏任务是由宿主(浏览器、Node)发起的,而微任务由 JS 自身发起。

宏任务(Macrotask)微任务(Microtask)
setTimeoutrequestAnimationFrame(有争议)
setIntervalMutationObserver(浏览器环境)
MessageChannelPromise.[ then/catch/finally ]
I/O事件队列process.nextTick(Node环境)
setImmediate(Node环境)queueMicrotask
script(整体代码块)

先执行同步函数,再执行微任务,后执行宏任务

如何理解 script(整体代码块)是个宏任务呢?

实际上如果同时存在两个 script 代码块,会首先在执行第一个 script 代码块中的同步代码,如果这个过程中创建了微任务并进入了微任务队列,第一个 script 同步代码执行完之后,会首先去清空微任务队列,再去开启第二个 script 代码块的执行。所以这里应该就可以理解 script(整体代码块)为什么会是宏任务。

console.log(0)
setTimeout(function(){
  console.log(1)
})

new Promise(function(resolve){
  console.log(2)
  resolve(3)
}).then(function(res){
  console.log(res)
})

async function async1() {
  console.log(4)
  await async2()
  console.log(5)
}

async function async2() {
  console.log(6)
} 
async1().then(function(res){
  console.log(res)
})
console.log(7)

// 答案
0246735undefined1

 

- Node事件循环机制(Event Loop)?

javascript从诞生之日起就是一门 单线程的 非阻塞的 脚本语言,单线程意味着,javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务,非阻塞靠的就是 event loop(事件循环),本文就讲解下事件循环。

event loop它最主要是分三部分:主线程、宏队列(macrotask)、微队列(microtask)

执行顺序
1、先执行主线程
2、遇到宏队列(macrotask)放到宏队列(macrotask)
3、遇到微队列(microtask)放到微队列(microtask)
4、主线程执行完毕
5、执行微队列(microtask),微队列(microtask)执行完毕
6、执行一次宏队列(macrotask)中的一个任务,执行完毕
7、执行微队列(microtask),执行完毕
8、依次循环。。。

摘抄:

- === 和 ==的不同

=== 比较值、类型都相等
== 比较值相等

1、“===” 的比较规则
先检查两个操作数的数据类型是否相同
如果相同,则比较两个数是否相等
如果不同,返回 false

2、“==” 的比较规则
先检查两个操作数的数据类型是否相同
如果相同,则比较两个数是否相等
如果不同,则先将两个数转换为相同数据类型,再进行比较

null === undefined
false
null == undefined
true

 

- 函数,箭头函数和构造函数?

1、函数
函数声明式有提升,
函数表达式没有提升。
2、箭头函数
(1)、只能写函数表达式。不能写声明式函数。
(2)、箭头函数的this指向问题:箭头函数会改变函数体内部this的指向,即每一个函数都会形成一个针对于this的封闭作用域,如果这是一个箭头函数则不会形成封闭作用域。这个箭头函数中的this指向会穿透本层到达上一层作用域上,以上一层this的指向作为本层this的指向。
(3)、箭头函数内部没有 arguments 这个参数集合
3、构造函数
实例化对象时一定需要new关键字。
 

- 箭头函数和普通函数的区别

1、箭头函数的this值在声明时就确认了,普通函数的this值,在调用的时候确认
2、call、apply、bind不会改变箭头函数this值,会改变普通函数this值
3、箭头函数不能作为构造函数使用,不能使用new
4、箭头函数没有原型属性
5、箭头函数不绑定arguments,取而代之用rest参数… 解决
6、箭头函数不能当做Generator函数,不能使用yield关键字
 

- 原生js的ajax请求?

1.创建XMLHTTPRequest对象
2.使用open方法设置和服务器的交互信息
3.设置发送的数据,开始和服务器端交互
4.注册事件
5.更新界面
6.取消请求用abort方法

//步骤一:创建异步对象
var ajax = new XMLHttpRequest();
//步骤二:设置请求的url参数,参数一是请求的类型,参数二是请求的url,可以带参数,动态的传递参数starName到服务端
ajax.open('get','getStar.php?starName='+name);
//步骤三:发送请求
ajax.send();
//步骤四:注册事件 onreadystatechange 状态改变就会调用
ajax.onreadystatechange = function () {
   if (ajax.readyState==4 &&ajax.status==200) {
    //步骤五 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
    console.log(ajax.responseText);//输入相应的内容
    }
}

摘抄:

- axios使用和原理?

axios是一个基于promise封装好的发送请求、返回响应的http库,可以应用在浏览器中和node.js中。

axios的特性:
1、在浏览器中发送请求会创建 XMLHttpRequests
2、在 node.js 发送请求会创建 http请求
3、Promise封装,故支持Promise API
4、支持拦截器interceptors,可以分别设置请求拦截和响应拦截,在发出请求和响应到达then之前进行判断处理。
5、转换请求数据和响应数据
6、取消请求
7、自动转换 JSON 数据
8、客户端支持防御 XSRF攻击

摘抄:

- 视频直播推流、拉流?

点播:flv,m3u8格式
回放:mp4,m3u8格式

摘抄:

- 网站的重定向?

1、配置nginx
2、window.location

window.location.replace("http://www。example.com");
window.location.href = "http://www.example.com";
window.location.assign('http://www.example.com')

3、

<!-- META Refresh META刷新 -->
<meta http-equiv="refresh" content="0;url=http://evil.com/" />
<!-- META Location META元的位置 -->
<meta http-equiv="location" content="URL=http://evil.com" />

 

- 网路七层协议图?

1、应用层:http,https,rtmp,dns
2、应用层
3、会话层
4、传输层:tcp,udp
5、网络层:ip
6、数据链路层
7、物理层
在这里插入图片描述
摘抄:

- 浏览器页面加载过程 ?

1.DNS域名解析
2.建立TCP连接
3.发送HTTP请求
4.服务器处理请求
5.返回响应结果
6.关闭TCP连接
7.浏览器解析HTML
1>构建DOM Tree
2>构建CSSOM
3>构建Render Tree
4>布局(Layout)
5>绘制(Painting)
8>JS的加载

摘抄:

- 理解http浏览器的协商缓存和强制缓存?

  1. 缓存可以减少冗余的数据传输。节省了网络带宽,从而更快的加载页面。
  2. 缓存降低了服务器的要求,从而服务器更快的响应。

那么我们使用缓存,缓存的资源文件到什么地方去了呢?
那么首先来看下 memory cache 和 disk cache 缓存
memory cache: 它是将资源文件缓存到内存中。等下次请求访问的时候不需要重新下载资源,而是直接从内存中读取数据。
disk cache: 它是将资源文件缓存到硬盘中。等下次请求的时候它是直接从硬盘中读取。

那么他们两则的区别是?
memory cache(内存缓存)退出进程时数据会被清除,而disk cache(硬盘缓存)退出进程时数据不会被清除。内存读取比硬盘中读取的速度更快。但是我们也不能把所有数据放在内存中缓存的,因为内存也是有限的。
memory cache(内存缓存)一般会将脚本、字体、图片会存储到内存缓存中。
disk cache(硬盘缓存) 一般非脚本会存放在硬盘中,比如css这些。
缓存读取的原理:先从内存中查找对应的缓存,如果内存中能找到就读取对应的缓存,否则的话就从硬盘中查找对应的缓存,如果有就读取,否则的话,就重新网络请求。

那么浏览器缓存它又分为2种:强制缓存和协商缓存。

协商缓存原理:客户端向服务器端发出请求,服务端会检测是否有对应的标识,如果没有对应的标识,服务器端会返回一个对应的标识给客户端,客户端下次再次请求的时候,把该标识带过去,然后服务器端会验证该标识,如果验证通过了,则会响应304,告诉浏览器读取缓存。如果标识没有通过,则返回请求的资源。

摘抄:

- HTTP与HTTPS的区别?

TTPS和HTTP的区别主要如下:
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

摘抄:

- TCP、UDP协议及两者的区别?

1) TCP提供面向连接的传输,通信前要先建立连接(三次握手机制); UDP提供无连接的传输,通信前不需要建立连接。
2) TCP提供可靠的传输(有序,无差错,不丢失,不重复); UDP提供不可靠的传输。
3) TCP面向字节流的传输,因此它能将信息分割成组,并在接收端将其重组; UDP是面向数据报的传输,没有分组开销。
4) TCP提供拥塞控制和流量控制机制; UDP不提供拥塞控制和流量控制机制。

摘抄:

- HTTP与WebSocket的区别

(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
(7)Websocket使用和 HTTP 相同的 TCP 端口,可以绕过大多数防火墙的限制。默认情况下,Websocket协议使用80端口;运行在TLS之上时,默认使用443端口。

相同点
1.都是基于TCP协议基础上,都是可靠性传输协议。HTTP如此,websocket亦如此
2.都是需要经过request,response阶段,其中websocket在发起请求的时候其实相当于借用了http的头部格式,区别就在于websocket请求头部有一个upgrade:websocket这样的字段(当然还有其他字段,但是这个字段最为关键)所以端口号是相同的不易被屏蔽。
3.如果请求失败,返回的错误编号都是相同的,例如:4**等
4、都是应用层协议。

不同点
1.正如前面所说,websocket的请求的头部会跟http请求头部有区别,比如多了一个upgrade:websocket字段
2.websocket只能是直连,不能通过代理来转发。究其原因应该怕如果通过代理转发的话,一个代理要承受如此多的websocket连接不释放,类似于一次DDOS攻击了。
3.websocket传输的数据是二进制流,是以帧为单位的,http传输的是明文传输,是字符串传输
4.websocket是全双工通信,有点类似于socket通信,在建立连接之后不必再像http那样你一个request我才回一个response了,想发就发,收发自如。
5、WebSocket是双向通信协议,模拟Socket协议,可以双向发送或接受信息。HTTP是单向的。
6、WebSocket是需要握手进行建立连接的。

摘抄:

- 开发一个好的组件,需要考虑哪些?

1、单一指责原则
2、可扩展性,维护性,重用性
3、低耦合, 高内聚
4、降低开发的复杂性
 

- 为什么 0.1 + 0.2 != 0.3 ?5.1 是什么导致了这种情况?

原因很简单,JS 采用的是双精度版本,这个版本就存在精度问题,就导致了上边这种情况。

内部的原理是什么?

我们计算机的信息全部转化为二进制进行存储的,那么0.1的二进制表示的是一个无限循环小数,该版本的 JS 采用的是浮点数标准需要对这种无限循环的二进制进行截取,从而导致了精度丢失,造成了0.1不再是0.1,截取之后0.1变成了 0.100…001,0.2变成了0.200…002。所以两者相加的数大于0.3。

那好,既然0.1不等于0.1了,那为什么我在控制台上输出console.log(0.1)还等于0.1呢?

因为在输入内容进行转换的时候,二进制转换成十进制,然后十进制转换成字符串,在这个转换的过程中发生了取近似值,所以打印出来的是一个近似值。
 

- 如何使用 javascript 获取语音数据并播放?

- cookie和session的详解与区别?

1、数据存放位置不同
cookie数据存放在客户的浏览器上,session数据放在服务器上。

2、安全程度不同
cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。

3、性能使用程度不同
session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。

4、数据存储大小不同
单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie,而session则存储与服务端,浏览器对其没有限制。

5、会话机制不同
session会话机制:session会话机制是一种服务器端机制,它使用类似于哈希表(可能还有哈希表)的结构来保存信息。
cookies会话机制:cookie是服务器存储在本地计算机上的小块文本,并随每个请求发送到同一服务器。 Web服务器使用HTTP标头将cookie发送到客户端。在客户端终端,浏览器解析cookie并将其保存为本地文件,该文件自动将来自同一服务器的任何请求绑定到这些cookie。

- HTTP1.0和HTTP1.1和HTTP2.0的区别?

摘抄:

名称解释

- 低耦合, 高内聚的含义是什么?

高内聚
内聚就是一个模块内各个元素彼此结合的紧密程度, 高内聚就是一个模块内各个元素彼此结合的紧密程度高. 所谓高内聚实质一个软件模块是由相关性很强的代码组成, 只负责一项任务, 也就是常说的单一责任原则.

低耦合
耦合: 一个软件结构内不同模块之间互连程度的度量(耦合性也叫块间联系,指软件系统模块中各模块间相互联系紧密程度的一种度量. 模块之间联系越紧密, 其耦合性就越强, 模块的独立性则越差, 模块间耦合的高低取决于模块间接口的复杂性, 调用的方式以及传递的信息.)对于低耦合, 粗浅的理解是: 一个完整的系统, 模块与模块之间, 尽可能的使其独立存在, 也就是说, 让每个模块, 尽可能的独立完成某个特定的子功能. 模块与模块之间的接口, 尽量的少而简单. 如果某两个模块间的关系比较复杂的话, 最好首先考虑进一步的模块划分. 这样有利于修改和组合.

模块之间存在依赖, 导致改动可能会互相影响, 关系越紧密, 耦合越强, 模块独立性越差

为什么要追求高内聚和低耦合
  软件架构设计的目的简单说就是在保持软件内在联系的前提下,分解软件系统,降低软件系统开发的复杂性,而分解软件系统的基本方法无外乎分层和分割。但是在保持软件内在联系的前提下,如何分层分割系统,分层分割到什么样的粒度,并不是一件容易的事,这方面有各种各样的分解方法,比如:关注点分离,面向方面,面向对象,面向接口,面向服务,依赖注入,以及各种各样的设计原则等,而所有这些方法都基于高内聚,低耦合的原则。 高内聚和低耦合是相互矛盾的,分解粒度越粗的系统耦合性越低,分解粒度越细的系统内聚性越高,过度低耦合的软件系统,软件模块内部不可能高内聚,而过度高内聚的软件模块之间必然是高度依赖的,因此如何兼顾高内聚和低耦合是软件架构师功力的体现。   高内聚,低耦合的系统有什么好处呢?事实上,短期来看,并没有很明显的好处,甚至短期内会影响系统的开发进度,因为高内聚,低耦合的系统对开发设计人员提出了更高的要求。高内聚,低耦合的好处体现在系统持续发展的过程中,高内聚,低耦合的系统具有更好的重用性,维护性,扩展性,可以更高效的完成系统的维护开发,持续的支持业务的发展,而不会成为业务发展的障碍.
摘抄:

- 什么叫优雅降级和渐进增强?

渐进增强 progressive enhancement
针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

优雅降级 graceful degradation
一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

区别:

a. 优雅降级是从复杂的现状开始,并试图减少用户体验的供给
b. 渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要
c. 降级(功能衰减)意味着往回看;而渐进增强则意味着朝前看,同时保证其根基处于安全地带
 

- 重绘和回流的区别?

重绘:元素样式的改变(但宽高、大小、位置等不变)
回流:元素的大小或者位置发生改变(当页面布局和几何信息发生改变的时候),触发了重新布局导致渲染树重新计算布局和渲染

注意:回流一定会触发重绘,而重绘不一定会回流
摘抄:

- 内存污染、内存泄漏、内存溢出的理解?

内存泄露:一个变量如果不用了,会被程序自动回收。内存泄露:垃圾回收不了这个东 西了,就是内存泄露。内存泄漏指由于疏忽或错误造成程序未能释放已经不再使用的内存。
内存溢出:系统会给每个对象分配内存也就是Heap size值,当对象所需要的内存大于 了系统分配的内存,就会造成内存溢出
内存污染:变量命名产生冲突
 

- AMD、CMD、ES6、CommonJS的区别?

CommonJS:模块引用(require) 模块输出(exports) 模块标识(module)
ES6:模块引用(import) 模块输出(export)
1、前者支持动态导入,也就是 require(${path}/xx.js),后者目前不支持。
2、、前者是同步导入,因为用于服务端,文件都在本地,同步导入即使卡住主线程影响也不大。而后者是异步导入,因为用于浏览器,需要下载文件,如果也采用同步导入会对渲染有很大影响。
3、前者在导出时都是值拷贝,就算导出的值变了,导入的值也不会改变,所以如果想更新值,必须重新导入一次。但是后者采用实时绑定的方式,导入导出的值都指向同一个内存地址,所以导入值会跟随导出值变化
AMD、CMD都使用define定义模块,require引入模块,区别在于AMD是前置依赖,CMD是就近依赖

vue

- MVC、MVP、MVVM模式的概念与区别?

摘抄:

- vue3带来的新特性/亮点?

  1. Performance
    vue3在性能方面比vue2快了2倍。
    重写了虚拟DOM的实现
    运行时编译
    update性能提高
    SSR速度提高

  2. Tree-shaking support
    vue3中的核心api都支持了tree-shaking,这些api都是通过包引入的方式而不是直接在实例化时就注入,只会对使用到的功能或特性进行打包(按需打包),这意味着更多的功能和更小的体积。

  3. Composition API
    vue2中,我们一般会采用mixin来复用逻辑代码,用倒是挺好用的,不过也存在一些问题:例如代码来源不清晰、方法属性等冲突。基于此在vue3中引入了Composition API(组合API),使用纯函数分隔复用代码。和React中的hooks的概念很相似。

摘抄:

- Vue框架总结之vue的优点?

vue的优点
轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十kb;
简单易学:国人开发,中文文档,不存在语言障碍 ,易于理解和学习;
双向数据绑定:保留了angular的特点,在数据操作方面更为简单;
组件化:保留了react的优点,实现了html的封装和重用,在构建单页面应用方面有着独特的优势;
视图,数据,结构分离:使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作;
虚拟DOM:dom操作是非常耗费性能的,不再使用原生的dom操作节点,极大解放dom操作,但具体操作的还是dom不过是换了另一种方式;
运行速度更快:相比较与react而言,同样是操作虚拟dom,就性能而言,vue存在很大的优势。

摘抄:

- vue核心之虚拟DOM(vdom)?

浏览器渲染引擎工作流程都差不多,大致分为5步,创建DOM树——创建StyleRules——创建Render树——布局Layout——绘制Painting

摘抄:

- 虚拟DOM的优势在哪里?

DOM 引擎、JS 引擎 相互独立,但又工作在同一线程(主线程) JS 代码调用 DOM API 必须 挂起 JS 引擎、转换传入参数数据、激活 DOM 引擎,DOM 重绘后再转换可能有的返回值,最后激活 JS 引擎并继续执行若有频繁的 DOM API 调用,且浏览器厂商不做“批量处理”优化, 引擎间切换的单位代价将迅速积累若其中有强制重绘的 DOM API 调用,重新计算布局、重新绘制图像会引起更大的性能消耗。

其次是 VDOM 和真实 DOM 的区别和优化:

虚拟 DOM 不会立马进行排版与重绘操作
虚拟 DOM 进行频繁修改,然后一次性比较并修改真实 DOM 中需要改的部分,最后在真实 DOM 中进行排版与重绘,减少过多DOM节点排版与重绘损耗
虚拟 DOM 有效降低大面积真实 DOM 的重绘与排版,因为最终与真实 DOM 比较差异,可以只渲染局部

摘抄:

-vue computed和watch的区别是什么?

计算属性computed :

1、支持缓存,只有依赖数据发生改变,才会重新进行计算
2、不支持异步,当computed内有异步操作时无效,无法监听数据的变化
3、computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
4、如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
5、如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。

侦听属性watch

1、不支持缓存,数据变,直接会触发相应的操作;
2、watch支持异步;
3、监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
4、当一个属性发生变化时,需要执行对应的操作;一对多;
5、监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数,
  immediate:组件加载立即触发回调函数执行,
  deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。
  
摘抄:

- keep-alive 的应用?

vue2.0提供了一个keep-alive组件用来缓存组件,避免多次加载相应的组件,减少性能消耗

keep-alive是Vue.js的一个内置组件。它能够不活动的组件实例保存在内存中,而不是直接将其销毁,它是一个抽象组件,不会被渲染到真实DOM中,也不会出现在父组件链中。

它有两个生命周期:
activated: keep-alive组件激活时调用
deactivated: keep-alive组件停用时调用
它提供了include与exclude两个属性,允许组件有条件地进行缓存。

keep-alive生命周期,生命周期执行顺序
1、不使用keep-alive的情况:beforeRouteEnter --> created --> mounted --> destroyed
2、使用keep-alive的情况:beforeRouteEnter --> created --> mounted --> activated --> deactivated
3、使用keep-alive,并且再次进入了缓存页面的情况:beforeRouteEnter -->activated --> deactivated

被keep-alive包裹住的页面都会被缓存,如果想刷新部分内容要启用activated函数,用法同created,activated只有在被keep-alive包裹时会触发,activated函数一进入页面就触发

摘抄:

- hash路由和history路由的区别?

1.hash路由在地址栏URL上有#,而history路由没有会好看一点
2.我们进行回车刷新操作,hash路由会加载到地址栏对应的页面,而history路由一般
就404报错了(刷新是网络请求,没有后端准备时会报错)。
3.hash路由支持低版本的浏览器,而history路由是HTML5新增的API。
4.hash的特点在于它虽然出现在了URL中,但是不包括在http请求中,所以对于后端是
没有一点影响的,所以改变hash不会重新加载页面,所以这也是单页面应用的必备。
5.history运用了浏览器的历史记录栈,之前有back,forward,go方法,之后在HTML5
中新增了pushState()和replaceState()方法(需要特定浏览器的支持),它们提供了
对历史记录进行修改的功能,不过在进行修改时,虽然改变了当前的URL,但是浏览器不会
马上向后端发送请求。

- vue总结的面试问题

摘抄:

webpack

-什么是loader,什么是plugin?

**loader:**loader用于加载某些资源文件。因为webpack本身只能打包common.js规范的js文件,对于其他资源如css,img等,是没有办法加载的,这时就需要对应的loader将资源转化,从而进行加载。

**plugin:**plugin用于扩展webpack的功能。不同于loader,plugin的功能更加丰富,比如压缩打包,优化,不只局限于资源的加载。

webpack常用loader
style-loader, css-loader, sass-loader, file-loader, babel-loader

webpack常用plugins
1、htmlWebpackPlugin:作用是依据一个简单的模板,帮助生成最终的html,html自动引用了打包后的js文件
2、hotModuleReplacement:允许在修改组件代码后,自动刷新实时预览修改后的效果。
3、clean-webpack-plugin:在webpack打包时清理dist目录
 

- grunt/gulp和webpack有什么不同呢?

1、grunt/gulp更加强调的是前端流程的自动化,模块化不是它的核心。
2、webpack更加强调模块化开发管理,而文件压缩合并、预处理等功能,是他附带的功能。
gulp,grunt是web构建工具
webpack是模块化方案
gulp,grunt是基于任务和流
webpack基于入口文件

webpack是一个模块打包器,强调的是一个前端模块化方案,更侧重模块打包,我们可以把开发中的所有资源都看成是模块,通过loader和plugin对资源进行处理。

gulp是一个前端自动化构建工具,强调的是前端开发的工作流程,可以通过配置一系列的task,第一task处理的事情(如代码压缩,合并,编译以及浏览器实时更新等)。然后定义这些执行顺序,来让glup执行这些task,从而构建项目的整个开发流程。自动化构建工具并不能把所有的模块打包到一起,也不能构建不同模块之间的依赖关系。
 

- webpack的构建流程是什么?

1、Webpack首先会把配置参数和命令行的参数及默认参数合并,并初始化需要使用的插件和配置插件等执行环境所需要的参数;初始化完成后会调用Compiler的run来真正启动webpack编译构建过程,webpack的构建流程包括compile、make、build、seal、emit阶段,执行完这些阶段就完成了构建过程。这其实就是我们上面所讲到的。
2、初始化参数: 从配置文件和 Shell 语句中读取与合并参数,得出最终的参数。
3、开始编译: 根据我们的webpack配置注册好对应的插件调用 compile.run 进入编译阶段,在编译的第一阶段是 compilation,他会注册好不同类型的module对应的 factory,不然后面碰到了就不知道如何处理了。
4、编译模块: 进入 make 阶段,会从 entry 开始进行两步操作:第一步是调用 loaders 对模块的原始代码进行编译,转换成标准的JS代码, 第二步是调用 acorn 对JS代码进行语法分析,然后收集其中的依赖关系。每个模块都会记录自己的依赖关系,从而形成一颗关系树。
5、输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会。
6、输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
摘抄:

- 什么是bundle,什么是chunk,什么是module?

module:是开发中的单个模块
chunk:是指webpack在进行模块依赖分析的时候,代码分割出来的代码块
bundle:是由webpack打包出来的文件
 

- webpack的优势?

1、代码拆分(支持异步模块加载)
2、Loader(支持任意模块加载,比如图片、less、css等等)
3、智能解析
4、插件系统
5、快速运行
摘抄:

- 网站性能优化?

一、webpack优化
1、Tree-sharking?
tree-sharking 是指在打包中去除那些引入了,但是在代码中没有被用到的那些死代码。
2、压缩
1>js压缩:UglifyJsPlugin
2>html压缩:HtmlWebpackPlugin
3>css压缩:MiniCssExtractPlugin
3、优化Loader搜索范围:排除exclude
4、提取公共代码
如果项目中没有去将每个页面的第三方库和公共模块提取出来,则项目会存在以下问题:
相同的资源被重复加载,浪费用户的流量和服务器的成本。
每个页面需要加载的资源太大,导致网页首屏加载缓慢,影响用户体验。
所以我们需要将多个页面的公共代码抽离成单独的文件,来优化以上问题 。Webpack 内置了专门用于提取多个Chunk 中的公共部分的插件 CommonsChunkPlugin
5、构建结果输出分析
Webpack 输出的代码可读性非常差而且文件非常大,让我们非常头疼。为了更简单、直观地分析输出结果,社区中出现了许多可视化分析工具。这些工具以图形的方式将结果更直观地展示出来,让我们快速了解问题所在。接下来讲解我们在 Vue 项目中用到的分析工具:webpack-bundle-analyzer 。
二、js
1、是否内存泄漏
2、代码中是否有死循环
三、cdn
1、cdn方式加载资源,不用对资源进行打包
2、可以配置cdn服务器,实现浏览器缓存
四、CSS放在页面最上部,javascript放在页面最下面
五、路由懒加载(按需加载,动态加载)
六、preload和prefetch
preload 加载资源一般是当前页面需要的,prefetch 一般是其它页面有可能用到的资源。

摘抄:

- 浏览器中的performance检测页面性能?

1.控制按钮。
2.overview。页面性能的高级汇总(FPS:帧率,CPU:CPU占用,NET:网络请求)
3.火焰图。CPU堆叠追踪的可视化(左侧名称是主线程的各种事件,Network:网络请求详细情况)
4.数据统计。以图表的形式汇总数据(summary:统计报表,Bottom-Up:事件时长顺序,Call Tree:事件调用顺序,Event log:事件发生的先后顺序)

摘抄:

微信小程序

- 小程序实现原理解析?

摘抄:

- 用uni-app开发小程序的优缺点有哪些?

优点

①兼容性好
Uni-app最大的特点就是一套代码编译以后多端通用,开发人员不需要在每个平台都单独开发一套代码就可以同时生成安卓、iOS、H5、百度小程序等等。节省了大量的成本。

②学习成本低
由于uni-app基于vue.js开发,因此对于前端开发工程师不会十分困难,学习uni-app的门槛也相应降低。尤其是封装的插件与微信端小程序相同。

③开发速度快
由于uni-app是用HBX进行开发,所以支持vue的语法。同时HBX的开发和编译速度都很快,这也是很多人选择uni-app的理由之一。

④拓展性强
Uni-app支持nvue,封装了H5+。同时,还支持原生的iOS和安卓开发。因此将原有的H5和移动端APP转移到uni-app上面十分方便。

⑤开发团队支持多
目前uni-app的开发团队DCloud发布新版本的频率比较频繁。新特性多,因此对于开发者也是有积极意义的。

缺点

①新平台问题多
虽然uni-app的有点很多,但毕竟是一个推出时间不多的的产品,因此在开发时难免会遇到一些问题。如果想要一个更稳定、坑更少的开发环境,建议选择其他平台。

②技术支持
如果在开发过程中遇到了问题,可能无法及时得到官方技术团队的回复。但是uni-app可以在QQ群或者微信群中相互交流。
 

开放性问题

- 端开发在人工智能时代能做什么?

摘抄:

- TensorFlow.js是什么?

摘抄:

- WebAssembly是什么?

WebAssembly(wasm)就是一个可移植、体积小、加载快并且兼容 Web 的全新格式。

实际上,WebAssembly是一种新的字节码格式,旨在成为高级语言的编译目标,目前可以使用C、C++、Rust、Go、Java、C#等编译器(未来还有更多)来创建wasm模块(见下图)。该模块以二进制的格式发送到浏览器,并在专有虚拟机上执行,与JavaScript虚拟机共享内存和线程等资源。

摘抄:

- Parcel 是什么?

Parcel 是一个前端构建工具,Parcel 官网 将它定义为极速零配置的Web应用打包工具。

Parcel 的特性
快速打包:启用多核编译,并具有文件系统缓存
打包所有资源:支持JS,CSS,HTML,文件资源等等 - 不需要安装任何插件
自动转换:使用 Babel,PostCSS 和 PostHTML 自动转换
零配置代码拆分:使用动态 import() 语法拆分您的输出包,只加载初始加载时所需的内容
模块热替换:不需要进行任何配置
友好的错误记录:以语法高亮的形式打印的代码帧,以帮助你查明问题

摘抄:

- 什么是 PWA?

PWA 是 Google 于 2016 年提出的概念,于 2017 年正式落地,于 2018 年迎来重大突破,全球顶级的浏览器厂商,Google、Microsoft、Apple 已经全数宣布支持 PWA 技术。

PWA 全称为 Progressive Web App,中文译为渐进式 Web APP,其目的是通过各种 Web 技术实现与原生 App 相近的用户体验。

纵观现有 Web 应用与原生应用的对比差距,如离线缓存、沉浸式体验等等,可以通过已经实现的 Web 技术去弥补这些差距,最终达到与原生应用相近的用户体验效果。

摘抄:

- 什么是postcss?

postcss 是一个用 JavaScript 工具和插件转换 CSS 代码的工具

摘抄:

- 浅谈对nodeJS的认识?

Nodejs是一个平台,构建在chrome的V8上(js语言解释器),采用事件驱动、非阻塞模型( c++库:libuv)。
摘抄:

- Nodejs:单线程为什么能支持高并发?

(1)前提:I/O密集型任务
(2)单线程的解释:主线程一个,底层工作线程多个。
(3)事件机制的底层依赖库:libuv、libeio、libev

摘抄:

- 什么是 web worker?

我们一直强调JavaScript是单线程的,但是web worker的出现使得JavaScript可以在多线程上跑,只是web worker本身适合用于一些复杂的、耗费cpu的运算,不能操作window、document、parent对象,所以说本质上的JavaScript还是单线程的。
web worker就是运行在后台的JavaScript,独立于其他脚本,不会影响页面的性能。您还可以做任意想做的事情,不会影响点击等操作。

为什么需要web worker?
对于耗时而不操作DOM的JavaScript,我们就可以使用web worker,增强性能。

摘抄:

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值