web面试题及答案_前端html面试题

2022-09-27 15:28:41 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

author: aSuncat JavaScript知识点大全:https://www.yuque.com/webfront/js

所有最新最全面试题,持续更新在语雀。见 语雀-前端面试题,欢迎点击关注~

阅读目录

  • html/ css:https://blog.csdn.net/aSuncat/article/details/88789368
  • javascript:2022年版(见语雀)、2019年版
  • es6:https://blog.csdn.net/aSuncat/article/details/88818661
  • vue:https://blog.csdn.net/aSuncat/article/details/88978775
  • react:2022年版(见语雀)、2019年版
  • jQuery:https://blog.csdn.net/aSuncat/article/details/108577468
  • webpack、gulp、grunt
  • node
  • 前后端通信http、https、tcp:https://blog.csdn.net/aSuncat/article/details/109180153
  • web安全
  • 前端性能
  • 浏览器:https://blog.csdn.net/aSuncat/article/details/116934548
  • 多端
  • 算法相关
  • 设计模式
  • 正则表达式
  • hybrid
  • 全栈
  • 项目
  • svn、git

webpack、gulp、grunt

11、前端技术体系 (1)多版本/覆盖 时间戳 发布新版本回滚 (2)ssr & 同构 (3)webpack vendor:commonchunk external:全局变量 默认css处理

模块化发展历程?

可从IIFE、AMD、CMD、CommonJS、UMD、webpack(require.ensure)、ES Module、<script type="module"> 这几个角度考虑。 参考答案 模块化主要是用来抽离公共代码,隔离作用域,避免变量冲突等。 IIFE:使用自执行函数来编写模块化,特点:在一个单独的函数作用域中执行代码,避免变量冲突。

代码语言:javascript复制
(function(){
  return {
    data:[]
  }
})()

AMD:使用requireJS 来编写模块化,特点:依赖必须提前声明好。

代码语言:javascript复制
define('./index.js',function(code){
    // code 就是index.js 返回的内容
})

CMD:使用seaJS 来编写模块化,特点:支持动态引入依赖文件。

代码语言:javascript复制
define(function(require, exports, module) {  
  var indexCode = require('./index.js');
})

CommonJS:nodejs 中自带的模块化。

代码语言:javascript复制
var fs = require('fs');

UMD:兼容AMD,CommonJS 模块化语法。 webpack(require.ensure):webpack 2.x 版本中的代码分割。 ES Modules:ES6 引入的模块化,支持import 来引入另一个 js 。

代码语言:javascript复制
import a from 'a';
  • webpack

webpack优化方式?

待完善

24、webpack在使用层面,对插件和loader不够理解。

  • gulp

1、

  • grunt

1、

grunt和gulp的区别?

1、易用:Gulp相比Grunt更简洁,而且遵循代码优于配置策略,维护Gulp更像是写代码。 2、高效:Gulp相比Grunt更有设计感,核心设计基于Unix流的概念,通过管道连接,不需要写中间文件。 3、高质量:Gulp的每个插件只完成一个功能,这也是Unix的设计原则之一,各个功能通过流进行整合并完成复杂的任务。例如:Grunt的imagemin插件不仅压缩图片,同时还包括缓存功能。他表示,在Gulp中,缓存是另一个插件,可以被别的插件使用,这样就促进了插件的可重用性。目前官方列出的有673个插件。 4、易学:Gulp的核心API只有5个,掌握了5个API就学会了Gulp,之后便可以通过管道流组合自己想要的任务。 5、流:使用Grunt的I/O过程中会产生一些中间态的临时文件,一些任务生成临时文件,其它任务可能会基于临时文件再做处理并生成最终的构建后文件。而使用Gulp的优势就是利用流的方式进行文件的处理,通过管道将多个任务和操作连接起来,因此只有一次I/O的过程,流程更清晰,更纯粹。 6、代码优于配置:维护Gulp更像是写代码,而且Gulp遵循CommonJS规范,因此跟写Node程序没有差别。


node

(1)nodejs 实践 (2)nodejs性能高在哪里 高并发非阻塞 IO 密集 (3)stream pipe 说不出背压机制 6、node 线上oom(通过重启,打profile,复现寻找bug点)。 基本的node性能监控 alinode等profile工具 浏览器渲染帧率、动画、性能相关,h5页面优化实践, 对小程序深度性能分析优化等方面很感兴趣 13、node服务线上的稳定,日志,安全,监控都有一定的了解,也有一定的线上运维经验

npm 模块安装机制,为什么输入 npm install 就可以自动安装对应的模块?

1.npm 模块安装机制: 发出npm install命令 查询node_modules目录之中是否已经存在指定模块 npm 向 registry 查询模块压缩包的网址 下载压缩包,存放在根目录下的.npm目录里 解压压缩包到当前项目的node_modules目录 若存在,不再重新安装 若不存在 2. npm 实现原理 输入 npm install 命令并敲下回车后,会经历如下几个阶段(以 npm 5.5.1 为例): (1)执行工程自身 preinstall 当前 npm 工程如果定义了 preinstall 钩子此时会被执行。 (2)确定首层依赖模块 首先需要做的是确定工程中的首层依赖,也就是 dependencies 和 devDependencies 属性中直接指定的模块(假设此时没有添加 npm install 参数)。 工程本身是整棵依赖树的根节点,每个首层依赖模块都是根节点下面的一棵子树,npm 会开启多进程从每个首层依赖模块开始逐步寻找更深层级的节点。 (3)获取模块 获取模块是一个递归的过程,分为以下几步:

  • 获取模块信息。在下载一个模块之前,首先要确定其版本,这是因为 package.json 中往往是 semantic version(semver,语义化版本)。此时如果版本描述文件(npm-shrinkwrap.json 或 package-lock.json)中有该模块信息直接拿即可,如果没有则从仓库获取。如 packaeg.json 中某个包的版本是 ^1.1.0,npm 就会去仓库中获取符合 1.x.x 形式的最新版本。
  • 获取模块实体。上一步会获取到模块的压缩包地址(resolved 字段),npm 会用此地址检查本地缓存,缓存中有就直接拿,如果没有则从仓库下载。
  • 查找该模块依赖,如果有依赖则回到第1步,如果没有则停止。 (4)模块扁平化(dedupe) 上一步获取到的是一棵完整的依赖树,其中可能包含大量重复模块。比如 A 模块依赖于 loadsh,B 模块同样依赖于 lodash。在 npm3 以前会严格按照依赖树的结构进行安装,因此会造成模块冗余。 从 npm3 开始默认加入了一个 dedupe 的过程。它会遍历所有节点,逐个将模块放在根节点下面,也就是 node-modules 的第一层。当发现有重复模块时,则将其丢弃。 这里需要对重复模块进行一个定义,它指的是模块名相同且 semver 兼容。每个 semver 都对应一段版本允许范围,如果两个模块的版本允许范围存在交集,那么就可以得到一个兼容版本,而不必版本号完全一致,这可以使更多冗余模块在 dedupe 过程中被去掉。 比如 node-modules 下 foo 模块依赖 lodash@^1.0.0,bar 模块依赖 lodash@^1.1.0,则 ^1.1.0 为兼容版本。 而当 foo 依赖 lodash@^2.0.0,bar 依赖 lodash@^1.1.0,则依据 semver 的规则,二者不存在兼容版本。会将一个版本放在 node_modules 中,另一个仍保留在依赖树里。 举个例子,假设一个依赖树原本是这样: node_modules – foo —- lodash@version1 – bar —- lodash@version2 假设 version1 和 version2 是兼容版本,则经过 dedupe 会成为下面的形式: node_modules – foo – bar – lodash(保留的版本为兼容版本) 假设 version1 和 version2 为非兼容版本,则后面的版本保留在依赖树中: node_modules – foo – lodash@version1 – bar —- lodash@version2 (5)安装模块 这一步将会更新工程中的 node_modules,并执行模块中的生命周期函数(按照 preinstall、install、postinstall 的顺序)。 (6)执行工程自身生命周期 当前 npm 工程如果定义了钩子此时会被执行(按照 install、postinstall、prepublish、prepare 的顺序)。 最后一步是生成或更新版本描述文件,npm install 过程完成。

了解v8引擎吗,一段js代码如何执行的?

在执行一段代码时,JS 引擎会首先创建一个执行栈 然后JS引擎会创建一个全局执行上下文,并push到执行栈中, 这个过程JS引擎会为这段代码中所有变量分配内存并赋一个初始值(undefined),在创建完成后,JS引擎会进入执行阶段,这个过程JS引擎会逐行的执行代码,即为之前分配好内存的变量逐个赋值(真实值)。 如果这段代码中存在function的声明和调用,那么JS引擎会创建一个函数执行上下文,并push到执行栈中,其创建和执行过程跟全局执行上下文一样。但有特殊情况,即当函数中存在对其它函数的调用时,JS引擎会在父函数执行的过程中,将子函数的全局执行上下文push到执行栈,这也是为什么子函数能够访问到父函数内所声明的变量。 还有一种特殊情况是,在子函数执行的过程中,父函数已经return了,这种情况下,JS引擎会将父函数的上下文从执行栈中移除,与此同时,JS引擎会为还在执行的子函数上下文创建一个闭包,这个闭包里保存了父函数内声明的变量及其赋值,子函数仍然能够在其上下文中访问并使用这边变量/常量。当子函数执行完毕,JS引擎才会将子函数的上下文及闭包一并从执行栈中移除。 最后,JS引擎是单线程的,那么它是如何处理高并发的呢?即当代码中存在异步调用时JS是如何执行的。比如setTimeout或fetch请求都是non-blocking的,当异步调用代码触发时,JS引擎会将需要异步执行的代码移出调用栈,直到等待到返回结果,JS引擎会立即将与之对应的回调函数push进任务队列中等待被调用,当调用(执行)栈中已经没有需要被执行的代码时,JS引擎会立刻将任务队列中的回调函数逐个push进调用栈并执行。这个过程我们也称之为事件循环。


  • koa

14、koa源码了解


web安全

Web攻击方式有哪几种?

1、CSRF 2、XSS 3、SQL注入攻击 就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。

简述HTTPS中间人攻击?

参考答案 https协议由 http ssl 协议构成,具体的链接过程可参考SSL或TLS握手的概述

中间人攻击过程如下: 服务器向客户端发送公钥。 攻击者截获公钥,保留在自己手上。 然后攻击者自己生成一个【伪造的】公钥,发给客户端。 客户端收到伪造的公钥后,生成加密hash值发给服务器。 攻击者获得加密hash值,用自己的私钥解密获得真秘钥。 同时生成假的加密hash值,发给服务器。 服务器用私钥解密获得假秘钥。 服务器用加秘钥加密传输信息

防范方法: 服务端在发送浏览器的公钥中加入CA证书,浏览器可以验证CA证书的有效性

  • CSRF

CSRF基本概念和缩写?

CSRF,Cross-site request forgery,通常被称为跨站请求伪造。

CSRF攻击原理?

1、前提:①用户在注册网站A登录过,②接口有漏洞。 2、引诱点击,往往是一个链接(这个链接自动携带cookie,不会带token),指向网站A的api,接口是get类型。浏览了A,浏览器自动生成新的cookie,网站A拿到cookie,接口运行。

CSRF防御措施?

1、token验证。 注册网站,或者访问网站,服务器自动向本地存储一个token。 2、refer验证。 服务器判断页面是不是我这个站点来的页面。 3、隐藏令牌。 http的head头,不会放在链接上。

  • XSS

XSS基本概念和缩写?

XSS,cross-site scripting ,跨域脚本攻击。

XSS攻击原理?

原理:向页面注入html标签或js脚本。 eg:提交区(评论区)写img标签,script标签,利用合法渠道向页面注入js

XSS防御措施?

宗旨:让xss不可执行。 1、前端替换关键字,如替换<&lt; >&gt; 2、后台替换。 3、任何内容写到页面之前都必须加以encode,避免不小心把html tag 弄出来。

  • CSRF ,XSS的区别

CSRF ,XSS的区别?

1、XSS是向页面注入js去运行,然后在js函数体中做他想做的事情。 CSRF是利用网站漏洞,自动执行接口。用户需要登陆网站。 2、XSS是获取信息,不需要提前知道其他用户页面的代码和数据包。 CSRF是代替用户完成指定的动作,需要知道其他用户页面的代码和数据包。

  • SQL注入

SQL注入防御措施?

1、永远不要信任用户的输入,要对用户的输入进行校验,可以通过正则表达式,或限制长度,对单引号和双”-“进行转换等。 2、永远不要使用动态拼装SQL,可以使用参数化的SQL或者直接使用存储过程进行数据查询存取。 3、永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。 4、不要把机密信息明文存放,请加密或者hash掉密码和敏感的信息。


前端性能

1、原则 (1)多使用内存、缓存或者其他方法。 (2)减少cpu占用,减少网络。

提升页面性能的方法有哪些?

一、加载页面和静态资源 1、静态资源压缩合并,减少http请求。 (1)减少http请求数量 (2)减少请求资源大小 2、非核心代码异步加载。 3、静态资源缓存:通过链接名称控制缓存,只有内容改变的时候,链接名称才会改变。 4、利用浏览器缓存 5、使用cdn让资源加载更快 6、预解析dns 7、使用ssr后端渲染,数据直接输出到html中(ssr:server site render) 二、页面渲染 1、css、js及放置位置 (1)尽量避免在HTML标签中写style属性 (2)css放前面,js放后面。 (3)避免使用CSS Expression 2、图片 (1)避免图片和iFrame等的空Src。空Src会重新加载当前页面,影响速度和效率 (2)懒加载(图片懒加载,下拉加载更多)

代码语言:javascript复制
<img id="img1" src="preview.jpg" data-realsrc="abc.jpg">
<script type="text/javascript">
var img1 = document.getElementById('img1');
img1.src = img1.getAttribute('data-realsrc');
</script>

3、dom操作 (1)减少dom查询,对dom查询做缓存。

代码语言:javascript复制
// 未缓存dom查询
var i;
for (i = 0; i < document.getElementsByTagName('p').length; i  ) {
	// todo
}
// 缓存了dom查询
var pList = document.getElementByTagName('p');
var i;
for (i = 0; i < pList.length; i  ) {
 // todo
}

(2)减少dom操作,多个操作尽量合并在一起执行。

代码语言:javascript复制
var frag = document.createDocumentFragment(); // 片段,循环插入dom,改成先插入到片段,再append到文档流

(3)用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能 4、事件 (1)尽早执行操作(如DOMContentLoaded) (2)事件节流

代码语言:javascript复制
var textarea = document.getElementById('text');
var timeoutId;
textarea.addEventListener('keyup', function() {
	if(timeoutId) {
		clearTimeout(timeoutId);
	}
	timeoutId = setTimeout(function() {
		// 触发change事件
	}, 100)
})

5、代码细节优化 (1)用hash-table来优化查找 (2)多个变量声明合并 (3)少用全局变量 (4)避免全局查询 (5)避免使用with(with会创建自己的作用域,会增加作用域链长度) (6)用setTimeout来避免页面失去响应 三、移动端性能优化 1、css (1)不滥用Float。Float在渲染时计算量比较大,尽量减少使用 (2)不滥用Web字体。Web字体需要下载,解析,重绘当前页面,尽量减少使用。 (3)避免使用css3渐变阴影效果。 2、css动画 (1)尽量使用css3动画,开启硬件加速。 可以用transform: translateZ(0)来开启硬件加速。 CSS中的属性(CSS3 transitions、CSS3 3D transforms、Opacity、Canvas、WebGL、Video)会触发GPU渲染,请合理使用。过渡使用会引发手机过耗电增加 3、合理使用requestAnimationFrame动画代替setTimeout 4、适当使用touch事件代替click事件。

什么是防抖和节流?有什么区别?如何实现??

防抖 触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间 思路: 每次触发事件时都取消之前的延时调用方法

代码语言:javascript复制
function debounce(fn) {
      let timeout = null; // 创建一个标记用来存放定时器的返回值
      return function () {
        clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
        timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
          fn.apply(this, arguments);
        }, 500);
      };
    }
    function sayHi() {
      console.log('防抖成功');
    }

    var inp = document.getElementById('inp');
    inp.addEventListener('input', debounce(sayHi)); // 防抖

节流 高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率 思路: 每次触发事件时都判断当前是否有等待执行的延时函数

代码语言:javascript复制
function throttle(fn) {
      let canRun = true; // 通过闭包保存一个标记
      return function () {
        if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
        canRun = false; // 立即设置为false
        setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
          fn.apply(this, arguments);
          // 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
          canRun = true;
        }, 500);
      };
    }
    function sayHi(e) {
      console.log(e.target.innerWidth, e.target.innerHeight);
    }
    window.addEventListener('resize', throttle(sayHi));
  • 非核心代码异步加载

异步加载的方式?

1、动态脚本加载 script标签,加入到body中 2、defer 加载js的时候,script标签加defer和async 3、async

异步加载的区别?

1、defer是在html解析完之后才会执行,如果是多个,按照加载的顺序依次进行。 2、async是在加载完之后立即执行,如果是多个,执行顺序和加载顺序无关。

  • 预解析dns

预解析dns的方式?

1、

代码语言:javascript复制
<link rel="dns-prefetch" href="//host_name_to_prefetch.com">

2、强制打开a标签的dns预解析

代码语言:javascript复制
<meta http-equiv="x-dns-prefetch-control" content="on">

页面中所有a标签,默认打开了dns预解析,如果链接是https开头的,默认关闭dns预解析


多端

小程序和 H5 有什么区别?

1、渲染方式与 H5 不同,小程序一般是通过 Native 原生渲染的,但是小程序同时也支持 web 渲染,如果使用 web 渲染的方式,我们需要初始化一个WebView 组件,然后在 WebView 中加载 H5 页面; 所以当我们开发一个小程序时,通常会使用 hybrid 的方式,即会根据具体情况选择部分功能用小程序原生的代码来开发,部分功能通过 WebView 加载 H5 页面来实现。Native 与 Web 渲染混合使用,以实现项目的最优解; 这里值得注意的是,小程序下,native 方式通常情况下性能要优于 web 方式。 2、小程序特有的双线程设计。 H5 下我们所有资源通常都会打到一个 bundle.js 文件里(不考虑分包加载),而小程序编译后的结果会有两个bundle,index.js封装的是小程序项目的 view 层,以及 index.worker.js 封装的是项目的业务逻辑,在运行时,会有两条线程来分别处理这两个bundle,一个是主渲染线程,它负责加载并渲染 index.js 里的内容,另外一个是 Service Worker线 程,它负责执行 index.worker.js 里封装的业务逻辑,这里面会有很多对底层api调用。


算法相关

通常情况下,搞金融的都会考算法。 一、排序

快速排序:https://segmentfault.com/a/1190000009426421 选择排序:https://segmentfault.com/a/1190000009366805 希尔排序:https://segmentfault.com/a/1190000009461832 二、堆栈、队列、链表 堆栈:https://juejin.im/entry/58759e79128fe1006b48cdfd 队列:https://juejin.im/entry/58759e79128fe1006b48cdfd 链表:https://juejin.im/entry/58759e79128fe1006b48cdfd (1)js数组本身就具备堆栈和队列特性。 (2)堆栈:先进后出。 三、递归 递归:https://segmentfault.com/a/1190000009857470 (1)60%的算法题都用到递归。 四、波兰式和逆波兰式 理论:http://www.cnblogs.com/chenying99/p/3675876.html 源码:https://github.com/Tairraos/rpn.js/blob/master/rpn.js

手写一个冒泡排序?

1、比较两个相邻的元素,如果后一个比前一个大,则交换位置。 2、 第一轮的时候最后一个元素应该是最大的一个。 3、按照第一步的方法进行两个相邻的元素的比较,由于最后一个元素已经是最大的了,所以最后一个元素不用比较。

代码语言:javascript复制
 function bubbleSort(arr) {
    let len = arr.length;
    for (let i = 0; i < len; i  ) {
       for (let j = 0; j < len - i - 1; j  ) { // j=0时,得到最大的元素,放在了最后面
         if (arr[j] > arr[j 1]) {
           [arr[j], arr[j 1]] = [arr[j 1], arr[j]];
         }
       }
    }
    return arr;
  }
  let arr = [3,5,1,2,7,8,4,5,3,4];
  let sortedArr = bubbleSort(arr);
  console.log(sortedArr);

快速排序的思想?

1、在数据集之中,找一个基准点,将数据分成两个部分,一部分比另外一部分所有的数据都要小, 2、建立两个数组,分别存储左边和右边的数组 3、利用递归进行下次比较

手写一个快速排序?

代码语言:javascript复制
 function quickSort(arr) {
    if (arr.length <= 1) { // 如果数组长度小于等于1无需判断直接返回即可
      return arr;
    }
    var pivotIndex = Math.floor(arr.length / 2); // 取基准点
    var pivot = arr.splice(pivotIndex, 1)[0]; // 取基准点的值,splice(index,1)函数可以返回数组中被删除的那个数
    var left = []; // 存放比基准点小的数组
    var right = []; // 存放比基准点大的数组
    for (var i = 0; i < arr.length; i  ) {  // 遍历数组,进行判断分配
      if (arr[i] < pivot) {
        left.push(arr[i]); // 比基准点小的放在左边数组
      } else {
        right.push(arr[i]); // 比基准点大的放在右边数组
      }
    }
    //递归执行以上操作,对左右两个数组进行操作,直到数组长度为<=1;
    return quickSort(left).concat([pivot], quickSort(right));
  };
  var arr = [1, 2, 3, 55, 7, 99, 8, 100, 1021];
  var sortedArr = quickSort(arr);
  console.log(sortedArr);

设计模式

用过哪些设计模式?

1、工厂模式:

主要好处就是可以消除对象间的耦合,通过使用工程方法而不是new关键字。将所有实例化的代码集中在一个位置防止代码重复。 工厂模式解决了重复实例化的问题 ,但还有一个问题,那就是识别问题,因为根本无法搞清楚他们到底是哪个对象的实例。

代码语言:javascript复制
function createObject(name,age,profession){//集中实例化的函数var obj = newObject();
    obj.name =name;
    obj.age = age;
    obj.profession= profession;
    obj.move =function () {
        returnthis.name   ' at '   this.age   ' engaged in '   this.profession;
    };
    return obj;
}
var test1 = createObject('trigkit4',22,'programmer');//第一个实例
var test2 =createObject('mike',25,'engineer');//第二个实例

2、构造函数模式 使用构造函数的方法 ,即解决了重复实例化的问题 ,又解决了对象识别的问题,该模式与工厂模式的不同之处在于: ①构造函数方法没有显示的创建对象 (new Object()); ②直接将属性和方法赋值给 this 对象; ③没有 renturn 语句。

JS的四种设计模式?

工厂模式 简单的工厂模式可以理解为解决多个相似的问题;

代码语言:javascript复制
function CreatePerson(name,age,sex) {
    var obj = new Object();
    obj.name = name;
    obj.age = age;
    obj.sex = sex;
    obj.sayName = function(){
        return this.name;
    }
    return obj;
}
var p1 = new CreatePerson("longen",'28','男');
var p2 = new CreatePerson("tugenhua",'27','女');
console.log(p1.name); // longen
console.log(p1.age);  // 28
console.log(p1.sex);  // 男
console.log(p1.sayName()); // longen

console.log(p2.name);  // tugenhua
console.log(p2.age);   // 27
console.log(p2.sex);   // 女
console.log(p2.sayName()); // tugenhua  

单例模式 只能被实例化(构造函数给实例添加属性与方法)一次

代码语言:javascript复制
// 单体模式
var Singleton = function(name){
    this.name = name;
};
Singleton.prototype.getName = function(){
    return this.name;
}
// 获取实例对象
var getInstance = (function() {
    var instance = null;
    return function(name) {
        if(!instance) {//相当于一个一次性阀门,只能实例化一次
            instance = new Singleton(name);
        }
        return instance;
    }
})();
// 测试单体模式的实例,所以a===b
var a = getInstance("aa");
var b = getInstance("bb");  

沙箱模式 将一些函数放到自执行函数里面,但要用闭包暴露接口,用变量接收暴露的接口,再调用里面的值,否则无法使用里面的值

代码语言:javascript复制
let sandboxModel=(function(){
    function sayName(){};
    function sayAge(){};
    return{
        sayName:sayName,
        sayAge:sayAge
    }
})()

发布者订阅模式 就例如如我们关注了某一个公众号,然后他对应的有新的消息就会给你推送,

代码语言:javascript复制
//发布者与订阅模式
    var shoeObj = {}; // 定义发布者
    shoeObj.list = []; // 缓存列表 存放订阅者回调函数

    // 增加订阅者
    shoeObj.listen = function(fn) {
        shoeObj.list.push(fn); // 订阅消息添加到缓存列表
    }

    // 发布消息
    shoeObj.trigger = function() {
            for (var i = 0, fn; fn = this.list[i  ];) {
                fn.apply(this, arguments);//第一个参数只是改变fn的this,
            }
        }
     // 小红订阅如下消息
    shoeObj.listen(function(color, size) {
        console.log("颜色是:"   color);
        console.log("尺码是:"   size);
    });

    // 小花订阅如下消息
    shoeObj.listen(function(color, size) {
        console.log("再次打印颜色是:"   color);
        console.log("再次打印尺码是:"   size);
    });
    shoeObj.trigger("红色", 40);
    shoeObj.trigger("黑色", 42);  

代码实现逻辑是用数组存贮订阅者, 发布者回调函数里面通知的方式是遍历订阅者数组,并将发布者内容传入订阅者数组

  • MVVM

对mvvm的理解?

1、MVVM 是 Model-View-ViewModel 的缩写。 2、Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。 3、View 代表UI 组件,它负责将数据模型转化成UI 展现出来。 4、ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。 5、在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。 ViewModel 通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。

mvvm框架实现的三要素/ vue的三要素?

1、响应式:vue如何监听到data的每个属性变化? (1)修改data属性后,vue立刻监听到。Object.defineProperty

代码语言:javascript复制
var __name = 'may';
Object.defineProperty(obj, 'name',{
	get: function() {
		return __name;
	},
	set: function(newVal) {
		__name = newVal; // 修改__name = 'april',obj.name就会变成april
	}
})

(2)data属性代理到vm上 2、模板引擎:vue的模板如何被解析,指令如何处理? (1)模板是什么 ①本质:字符串 ②有逻辑,如v-if, v-for等 ③与html格式很像,但有很大区别 ④模板最终必须转换成Js代码(js函数-render函数),因为 有逻辑(v-if, v-for),必须用js才能实现(图灵完美语言) 转换为html渲染页面,必须用js才能实现 (2)render函数 (3)render函数与vdom 3、渲染:vue的模板如何被渲染成Html?以及渲染过程?


正则表达式

写一个function,清除字符串前后的空格。(兼容所有浏览器)?

代码语言:javascript复制
function trim(str) {
	if (str && typeof str === 'string') {
		return str.replace(/(^s*)|(s*)$/g, '');
	}
}

hybrid

15、hybrid业务开发经验,对离线包机制熟悉,多各种优化方案也了解得比较清楚。

7、离线包加载和更新机制, 22、servive worker, web worker


全栈

8、图片加载的一个细节,能够从全栈角度给出一些高并发情况下的系统扩展思路 27、跨域access-control-allow-origin多域名白名单处理 cdn部署 前端框架选型 人员协调项目延期 整个部门没有用到mock平台,前后端分离 自己写了服务在服务端用webpack multi方式融合不同的业务模块打包 Mbox的数据管理方案(mbox的数据状态流转机制) 数据库,数据索引,事务,数据库锁的问题

5、前端核心监控数据来源(performance api 业务定义为主)

31、逻辑外链如何保持多个数据同步

项目

16、资讯类的项目,有哪些技术特点(本想了解list相关的回答) 详情里面做了哪些 详情页对性能要求高,有哪些优化?配置缓存来优化。 缓存如何配置, 哪些缓存头来控制的缓存 类似静态化的性能优化,采用ssr比较适合详情页的技术 1、哪些工作是偏技术的,需要技术来解决的

svn、git

get fetch、git pull的区别

1、git fetch是将远程主机的最新内容拉到本地,用户在检查了以后决定是否合并到工作本机分支中。 2、git pull 则是将远程主机的最新内容拉下来后直接合并,即:git pull = git fetch git merge,这样可能会产生冲突,需要手动解决。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/174796.html原文链接:https://javaforall.cn

0 人点赞