H5新特性

  • 语义特性
    • 易于用户阅读;样式丢失的时候能让页面呈现清晰的结构
    • 有利于SEO,搜索引擎根据标签来确定上下文和各个关键字的权重 方便其他设备解析,如盲人阅读器根据语义渲染网页 有利于开发和维护,
    • 语义化更具可读性,
    • 代码更好维护
  • 本地存储特性
  • 设备访问的特性
  • 连接特性
  • 网页多媒体特性
  • 三维、图形以及特效特性
  • 性能与集成特性

display和visible

display: none —不为被隐藏的对象保留其物理空间,即该对象在页面上彻底消失,通俗来说就是看不见也摸不到。

display: none—-将元素的显示设为无,即在网页中不占任何的位置。

visible: hidden— 使对象在网页上不可见,但该对象在网页上所占的空间没有改变,通俗来说就是看不见但摸得到。

visibility: hidden—-将元素隐藏,但是在网页中该占的位置还是占着。

隐藏方法:opacity: 0透明度调为0和visibility: hidden一样

跨域

浏览器同源策略:协议名、域名、端口号必须一致;
当页面在执行一个脚本时,会检查访问的资源是否同源,如果不是,就会报错。

注意:对于像 img、iframe、script 等标签的 src 属性是特例,它们是可以访问非同源网站的资源的。

  • jsonp
  • cors
    • Access-Control-Allow-Origin: *
  • PostMessage
  • websocket
  • node中间件代理(两次跨域)
  • nginx反向代理
  • window.name+iframe

onmouseover 和onmousemove的区别

时间上

onmousemove 事件触发后,再触发 onmouseover 事件。

动作上

onmouseover 只在刚进入区域时触发。

onmousemove 除了刚进入区域触发外,在区域内移动鼠标,也会触发该事件。

当鼠标移动很快时,可能不会触发这两个事件。

onmouseover与onmousemove的区别是:

当鼠标移过当前对象时就产生了onmouseover事件(onmouseover有个移入移出的过程)。

当鼠标在当前对象上移动时就产生了onmousemove事件,

只要是在对象上移动而且没有移出对象的,就是onmousemove事件。

  1. onmouseenter 不支持事件冒泡,onmouseover支持事件冒泡,
  2. onmouseenter跟onmouseover一样,鼠标进入一次目标元素事件处理程序就执行一次,而onmousemove在目标元素里鼠标坐标变化一次事件处理程序就执行一次

闭包和匿名函数

http://caibaojian.com/javascript-closure-fn.html

js闭包是指有权访问另一个函数作用域中的变量的函数,

引用了另一个函数作用域内变量的函数

闭包就是能够读取其他函数内部变量的函数。

由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成”定义在一个函数内部的函数”。

所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!

  function f1(){

    var n=999;

    function f2(){
      alert(n);
    }

    return f2;

  }

  var result=f1();

  result(); // 999
  • 闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

不同盒模型

ie盒中的width包括了padding和border,而w3c盒模型里width不包括。

要解决IE盒模型的问题就要使用<!DOCTYPE html>声明,告诉IE采用W3C盒子模型即可

EVENT LOOP(事件循环)

event loop是一个执行模型,在不同的地方有不同的实现。浏览器和NodeJS基于不同的技术实现了各自的Event Loop

宏队列,macrotask,也叫tasks。 一些异步任务的回调会依次进入macro task queue,等待后续被调用

  • script(整体代码)
  • setTimeout
  • setInterval
  • setImmediate
  • requestAnimationFrame
  • I/O
  • UI rendring

微队列 microtask

  • Process.nextTick
  • Promise
  • Object.observe(废弃)
  • MutationObserver

浏览器 Event Loop

JS 引擎首先在宏任务队列中取出第一个任务执行script,执行完毕后取出微任务队列中的所有任务顺序执行;之后再取宏任务,如此循环,直至两个队列的任务都取完。

  • 当浏览器执行 JS 代码时

    • 整体script作为第一个宏任务进入主线程。
    • 同步任务被放到执行栈,异步任务会进入Event Table并注册函数,其回调函数按类别被放到宏任务队列和微任务队列中。
    • 执行完所有同步任务后,开始读取任务队列中的结果。检查微任务队列,如果有任务则按顺序执行。
    • 执行完所有微任务后,开始下一个宏任务。如此循环,直到两个队列(宏任务队列和微任务队列)的任务都执行完。
  • 当然如果你在microtask中不断的产生microtask,那么其他宏任务macrotask就无法执行了,但是这个操作也不是无限的,拿NodeJS中的微任务process.nextTick()来说,它的上限是1000个,后面我们会讲到

vue2和vue3的双向绑定区别

vue2

  • object.defineProperty(obj, prop, desriptor)

    • 目标/属性/描述符

    • 描述符:

      • configrable 描述属性是否配置,以及可否删除(默认false)
      • enumerable 描述属性是否会出现在for in 或者 Object.keys()的遍历中 (默认false)
      • value 表示该属性对应的值(默认false)
      • writable 为true时才可以改变value
      • get/set
1
2
3
4
5
6
7
8
9
10
11
var bValue = 38;
Object.defineProperty(o, "b", {
// 使用了方法名称缩写(ES2015 特性)
// 下面两个缩写等价于:
// get : function() { return bValue; },
// set : function(newValue) { bValue = newValue; },
get() { return bValue; },
set(newValue) { bValue = newValue; },
enumerable : true,
configurable : true
});

vue3

  • proxy

为什么不用object.defineProperty

  1. 在Vue中,Object.defineProperty无法监控到数组下标的变化,
  2. Object.defineProperty只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。

什么是Proxy

ProxyES6 中新增的一个特性,翻译过来意思是”代理”,用在这里表示由它来“代理”某些操作。 Proxy让我们能够以简洁易懂的方式控制外部对对象的访问。其功能非常类似于设计模式中的代理模式。

Proxy可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

使用 Proxy的核心优点是可以交由它来处理一些非核心逻辑(如:读取或设置对象的某些属性前记录日志;设置对象的某些属性值前,需要验证;某些属性的访问控制等)。 从而可以让对象只需关注于核心逻辑,达到关注点分离,降低对象复杂度等目的。

基本用法:
1
let p = new Proxy(target, handler);
参数:

target: 是用Proxy包装的被代理对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
handler: 是一个对象,其声明了代理target 的一些操作,其属性是当执行一个操作时定义代理的行为的函数。

https://www.jianshu.com/p/e1dabd5e7386

https://www.jianshu.com/p/0c196cd8c245

BFC

BFC(Block formatting context)直译为”块级格式化上下文”。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。

BFC的布局规则

内部的Box会在垂直方向,一个接一个地放置。

Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。

每个盒子(块盒与行盒)的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。

BFC的区域不会与float box重叠。

BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。

计算BFC的高度时,浮动元素也参与计算。

溢出隐藏、清除浮动(overflow:hidden)

参考博客

由于父级元素没有高度,下面的元素会顶上去,造成页面的塌陷。因此,需要给父级加个overflow:hidden属性,这样父级的高度就随子级容器及子级内容的高度而自适应。

由于在IE比较低版本的浏览器中使用overflow:hidden;是不能达到这样的效果,因此需要加上 zoom:1;

所以为了让兼容性更好的话,如果需要使用overflow:hidden来清除浮动,那么最好加上zoom:1;

JWT(json web token)

JWT 的三个部分依次如下。

  • Header(头部)
  • Payload(负载)
  • Signature(签名)

Header 部分是一个 JSON 对象,描述 JWT 的元数据,通常是下面的样子。

1
2
3
4
{
"alg": "HS256",
"typ": "JWT"
}

上面代码中,alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT

Payload

Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。

Signature

Signature 部分是对前两部分的签名,防止数据篡改。

首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户。然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

1
2
3
4
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

算出签名以后,把 Header、Payload、Signature 三个部分拼成一个字符串,每个部分之间用”点”(.)分隔,就可以返回给用户。

客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。

此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

1
Authorization: Bearer <token>

另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。

JWT 的几个特点

(1)JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。

(2)JWT 不加密的情况下,不能将秘密数据写入 JWT。

(3)JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。

(4)JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。

(5)JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。

(6)为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

px\rem\em

PX

px像素(Pixel)。相对长度单位。像素px是相对于显示器屏幕分辨率而言的。

EM

em是相对长度单位。相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸。

EM特点

    1. em的值并不是固定的;
    1. em会继承父级元素的字体大小。

REM

rem是CSS3新增的一个相对单位(root em,根em),这个单位引起了广泛关注。这个单位与em有什么区别呢?区别在于使用rem为元素设定字体大小时,仍然是相对大小,但相对的只是HTML根元素。这个单位可谓集相对大小和绝对大小的优点于一身,通过它既可以做到只修改根元素就成比例地调整所有字体大小,又可以避免字体大小逐层复合的连锁反应。

原型和原型链

参考

原型

  • js 中一切皆对象
  • 每个对象都有__proto__属性,用于储存继承得来的方法和属性
  • 每个函数对象都有prototype属性,用于继承,将其中定义的属性和方法传递给‘后代’(比如实例化

每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个内部指针指向原型。

原型链

当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。

js事件机制

事件流

  • 事件捕获

    • 鼠标点击或者触发dom事件时,浏览器会从根节点开始由外到内进行事件传播,即点击了子元素,如果父元素通过事件捕获方式注册了对应的事件的话,会先触发父元素绑定的事件
  • 处于目标状态

  • 事件冒泡

    • 与事件捕获恰恰相反,事件冒泡顺序是由内到外进行事件传播,直到根节点
  • dom标准事件流的触发的先后顺序为:先捕获再冒泡

    • addEventListener(event, function, useCapture)
      • useCapture—是否采用事件捕获进行事件捕捉,默认为false,即采用事件冒泡方式
  • 阻止事件冒泡

    • e.stopPropagation();
  • 阻止默认事件

    • event.preventDefault();

position属性

absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。
fixed 生成绝对定位的元素,相对于浏览器窗口进行定位。元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。
relative 生成相对定位的元素,相对于其正常位置进行定位。因此,”left:20” 会向元素的 LEFT 位置添加 20 像素。
static 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。
inherit 规定应该从父元素继承 position 属性的值。

前端优化

  • script的defer和async标签(只对外部脚本)
    • defer:脚本在执行时不会改变页面结构,脚本会被延迟到整个页面都解析完毕后再进行。defer的脚本执行从上往下,将在DOMContentLoaded事件之前执行。
    • async:async的是脚本的执行不能保证先后次序,就是相当于告诉浏览器既不必等脚本解析执行完才加载页面,也不必等异步脚本下载执行后才加载其他脚本。将在页面的load事件前执行,但可能在DOMContentLoaded之前或之后
    • defer是延迟执行,而async是异步执行。
  • cdn
  • 路由懒加载
  • http2
  • SSR(服务器渲染)

CDN

利用最靠近每位用户的服务器,更快、更可靠地将音乐、图片、视频、应用程序及其他文件发送给用户,来提供高性能、可扩展性及低成本的网络内容传递给用户

有效利用浏览器缓存机制 用户在访问你网站时 访问其他网站 如果他们和你使用了一样的CDN静态资源 那么浏览器可以直接从本地获取这些资源

  • 缓存就是说我们把该资源copy一份到CDN服务器上的这个过程,

  • 回源就是说CDN发现自己没有这个资源(一般是缓存的数据过期了), 转头像根服务器,或者他的上层服务器去要这个资源。

diff算法

时间复杂度

两个树的完全的 diff 算法是一个时间复杂度为 O(n3) , Vue和react进行了优化 O(n3) 复杂度的问题转换成 O(n) 复杂度的问题(只比较同级不考虑跨级问题)

因为在前端操作dom的时候了,不会把当前元素作为上一级元素或下一级元素,很少会跨越层级地移动Dom元素,常见的都是同级的比较。 所 以 Virtual Dom只会对同一个层级的元素进行对比。

vue中diff算法的原理

在数据发生变化,vue是先根据真实DOM生成一颗 virtual DOM ,当 virtual DOM 某个节点的数据改变后会生成一个新的 Vnode ,然后 Vnode 和 oldVnode 作对比,发现有不一样的地方就直接修改在真实的DOM上,然后使 oldVnode 的值为 Vnode ,来实现更新节点。

webpeck

Webpack 是一个前端资源加载/打包工具。

loader

webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。loader 让 webpack 能够去处理其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。

删除的方法

detele

delete操作符可以删除隐式的全局变量、对象的自定义属性,而不能删除显示声明的全局变量,对象的内置和继承属性,而且在严格模式下,删除不能删 除的变量或属性时,直接抛出异常

reflect.deleteProperty()

1
2
3
var obj = { x: 1, y: 2 };
Reflect.deleteProperty(obj, "x"); // true
obj; // { y: 2 }

块元素和行元素

块元素:div,和h1~h6,p,hr,ol,ul

行元素:a,br,u,img

canvas和svg

Canvas是使用JavaScript在网页上绘制图像。SVG是使用XML描述2D图形的语言。

  • SVG具有丰富的DOM接口
  • Canvas绘制效率高
  • SVG不依赖分辨率
  • Canvas适合小面积大数量的应用,svg适合大面积小数量的应用
  • Canvas提供的功能更原始,适合像素处理,动态渲染和大数据量绘制。SVG功能更完善,适合静态图片展示,高保真文档查看和打印的应用场景

作用域和作用域链

作用域

在 JavaScript 中, 作用域为可访问变量,对象,函数的集合。也是他们可以访问的范围。

作用域链

当声明一个函数时,局部作用域一级一级向上包起来,就是作用域链。

1.当执行函数时,总是先从函数内部找寻局部变量

2.如果内部找不到(函数的局部作用域没有),则会向创建函数的作用域(声明函数的作用域)寻找,依次向上