重学前端

 

1、前端基础

  JS:

一、Promise、Async有什么区别

  1. Async 更简洁,不须要用 then 链接
  2. Promise 中不能自定义使用 try/catch 进行错误捕获,可是在 Async/await 中能够像处理同步代码处理错误javascript

  3. 调试更方便
  4. Generator 函数能够暂停执行和恢复执行,这是它能封装异步任务的根本缘由

二、介绍service worker

  1. 一个独立的 worker 线程,独立于当前网页进程,有本身独立的 worker context。css

  2. 一旦被 install,就永远存在,除非被 uninstallhtml

  3. 须要的时候能够直接唤醒,不须要的时候自动睡眠(有效利用资源,此处有坑)前端

  4. 可编程拦截代理请求和返回,缓存文件,缓存的文件能够被网页进程取到(包括网络离线状态)java

  5. 能向客户端推送消息node

  6. 不能直接操做 DOM,可是service worker能够经过postMessage与页面之间通讯,把消息通知给页面,若是须要的话,让页面本身去操做DOM。react

  7. 出于安全的考虑,必须在 HTTPS 环境下才能工做css3

  8. 异步实现,内部大都是经过 Promise 实现git

三、列举Es6,经常使用的一些新特性es6

  • let, const:新增块级做用域,分别定义变量和常量

  • class, extends, super:用class定义了一个“类”,能够看到里面有一个constructor方法,这就是构造方法,而this关键字则表明实例对象;Class之间能够经过extends关键字实现继承;super关键字,它指代父类的实例(即父类的this对象)30分钟掌握ES6/ES2015核心内容(上)

  • 箭头函数:函数体内的this对象,就是定义时所在的对象,而不是运行时时所在的对象。

  • 模板字符串(template string)

  • 解构(Destructuring)

  • ES6模块:(import export):ES6模块的设计思想,是尽可能的静态化,使得编译时就能肯定模块的依赖关系,以及输入和输出的变量。CommonJS和AMD模块,都只能在运行时肯定这些东西。30分钟掌握ES6/ES2015核心内容(下)

// 假设咱们有两个js文件: index.js和content.js,如今咱们想要在index.js中使用content.js返回的结果,咱们要怎么作呢?

//content.js
define('content.js', function(){
    return 'A cat';
})

// AMD
//index.js
require(['./content.js'], function(animal){
    console.log(animal);   //A cat
})

// CMD
//index.js
var animal = require('./content.js')

//content.js
module.exports = 'A cat'

// ES6
//index.js
import animal from './content'

//content.js
export default 'A cat'

  keys:获取对象键名,返回一个数组

  values:获取对象值,返回一个数组

  entries:把对象键值对转换成一个数组,返回一个包含键值对数组的新数组

  includes:用于某个数组或字符串是否包含给定的值,返回一个布尔值。若是没找到符合条件的成员就返回 underfind

参考资料以下:
ECMAScript 6 入门
ES6 Promise 用法讲解

四、说下本身对模块化开发的理解,以及模块化开发的好处

  • 提升开发效率,有利团队协同开发,
  • 避免全局变量污染,命名冲突,
  • 方便代码的复用维护等。

五、浏览器事件流向

  1. “DOM2级事件”规定事件流包括三个阶段,事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的事件捕获,为截获事件提供了机会,而后是实际的目标接收了事件,最后一个阶段是冒泡阶段
  2. 注意处于目标阶段的时候,既不是冒泡阶段、也不是捕获阶段,事件处理程序被调用的顺序是注册的顺序

六、类型转换规则 

[] == ![]
  • 逻辑非运算符使  ![] 转换为布尔值 false
  • 若是有一方是布尔值,就把布尔值转换成 number 0 再比较  [] == 0 
  • 若是一方是 object ,且另外一方为 stringnumberobject就先调用 valueOf   [].valueOf()   返回 [] 不是基本类型,再调用 toString 返回 '' ,最后将 '' 转换为 0
  • 转换顺序:object / 布尔值 -> string -> number

七、如何实现深拷贝?

  • 不少人认为 Object.assign 是用来深拷贝的,其实并非,Object.assign 只会拷贝全部的属性值到新的对象中,若是属性值是对象的话,拷贝的是地址,因此并非深拷贝。
  • 展开运算符 ...  Object.assign() 行为一致, 执行的都是浅拷贝(只遍历一层)
  • JSON.parse(JSON.stringify(object)) 能够用来深拷贝,但它会会忽略掉函数和 undefined 
  •  lodash 的深拷贝函数:
function deepClone(obj) {
  function isObject(o) {
    return (typeof o === 'object' || typeof o === 'function') && o !== null
  }

  if (!isObject(obj)) {
    throw new Error('非对象')
  }

  let isArray = Array.isArray(obj)
  // 扩展运算符只拷贝一层
  let newObj = isArray ? [...obj] : { ...obj }
  Reflect.ownKeys(newObj).forEach(key => {
    newObj[key] = isObject(obj[key]) ? deepClone(obj[key]) : obj[key]
  })

  return newObj
}

八、如何理解原型、原型链?

  • Object 是全部对象的爸爸,全部对象均可以经过 __proto__ 找到它
  • Function 是全部函数的爸爸,全部函数均可以经过 __proto__ 找到它
  • 函数的 prototype 是一个对象
  • 对象的 __proto__ 属性指向原型, __proto__ 将对象和原型链接起来组成了原型链

九、基本类型判断,如怎么区分数组和对象?

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

十、写一个通用的事件侦听器函数

      // 视能力分别使用dom0||dom2||IE方式 来绑定事件
         // 参数: 操做的元素,事件名称 ,事件处理程序
         addEvent : function(element, type, handler) {
             if (element.addEventListener) {
                 //事件类型、须要执行的函数、是否捕捉
                 element.addEventListener(type, handler, false);
             } else if (element.attachEvent) {
                 element.attachEvent('on' + type, function() {
                     handler.call(element);
                 });
             } else {
                 element['on' + type] = handler;
             }
         },
         // 移除事件
         removeEvent : function(element, type, handler) {
             if (element.removeEventListener) {
                 element.removeEventListener(type, handler, false);
             } else if (element.datachEvent) {
                 element.detachEvent('on' + type, handler);
             } else {
                 element['on' + type] = null;
             }
         },
         // 阻止事件 (主要是事件冒泡,由于IE不支持事件捕获)
         stopPropagation : function(ev) {
             if (ev.stopPropagation) {
                 ev.stopPropagation();
             } else {
                 ev.cancelBubble = true;
             }
         },
         // 取消事件的默认行为
         preventDefault : function(event) {
             if (event.preventDefault) {
                 event.preventDefault();
             } else {
                 event.returnValue = false;
             }
         },
         // 获取事件目标
         getTarget : function(event) {
             return event.target || event.srcElement;
         },
         // 获取event对象的引用,取到事件的全部信息,确保随时能使用event;
         getEvent : function(e) {
             var ev = e || window.event;
             if (!ev) {
                 var c = this.getEvent.caller;
                 while (c) {
                     ev = c.arguments[0];
                     if (ev && Event == ev.constructor) {
                         break;
                     }
                     c = c.caller;
                 }
             }
             return ev;
         }

十、用js实现千位分隔符

 /(\d)(?=(/d{3})+\.)/g 

    num.toString()
          .replace(/(\d)(?=(\d{3})+\.)/g, function($0, $1) {
              return $1 + ",";
          });

 

  CSS:

一、介绍css3中position: sticky

  • absolute 生成绝对定位的元素,相对于值不为 static的第一个父元素进行定位。
  • fixed (老IE不支持) 生成绝对定位的元素,相对于浏览器窗口进行定位。
  • relative 生成相对定位的元素,相对于其正常位置进行定位。
  • static 默认值。没有定位,元素出如今正常的流中(忽略 top, bottom, left, right z-index 声明)。
  • inherit 规定从父元素继承 position 属性的值。
  • sticky  相对于最近的块级父元素定位

 

  1. 父级元素不能有任何overflow:visible觉得的overflow设置,不然没有粘滞效果。由于改变了滚动容器(即便没有出现滚动条)。所以,若是你的position:sticky无效,看看是否是某一个祖先元素设置了overflow:hidden,移除之便可。
  2. 同一个父容器中的sticky元素,若是定位值相等,则会重叠;若是属于不一样父元素,则会鸠占鹊巢,挤开原来的元素,造成依次占位的效果

 二、浏览器的兼容性

  • png24位的图片在iE6浏览器上出现背景,解决方案是作成PNG8
  • 浏览器默认的margin和padding不一样。解决方案是加一个全局的*{margin:0;padding:0;}来统一
  • IE下,even对象有x,y属性,可是没有pageX,pageY属性; Firefox下,event对象有pageX,pageY属性,可是没有x,y属性
  • 一些新特性如 flex ,须要加前缀兼容不一样的浏览器
  • even对象 Chrome 等浏览器用 e.target、而 IE 用 e.srcElement
  • 给元素添加监听事件时,Chrome 等浏览器用的 addEventListener, 而IE 用 attachEvent

 

三、简述一下你对HTML语义化的理解?

  • 用正确的标签作正确的事情。
  • html语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析;
  • 即便在没有样式CSS状况下也以一种文档格式显示,而且是容易阅读的;
  • 搜索引擎的爬虫也依赖于HTML标记来肯定上下文和各个关键字的权重,利于SEO;
  • 便于阅读维护理解。

 

四、请描述一下 cookies,sessionStorage 和 localStorage 的区别?

 

  • 是否携带:cookie是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据(一般通过加密),会在 http 请求中携带(即便不须要)
  • 存储大小: cookie数据大小不能超过4k。 sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,能够达到5M或更大。
  • 有期时间: localStorage 存储持久数据,浏览器关闭后数据不丢失除非主动删除数据; sessionStorage 数据在当前浏览器窗口关闭后自动删除。 cookie 设置的cookie过时时间以前一直有效,即便窗口或浏览器关闭

五、frame有那些缺点?

  • *iframe会阻塞主页面的加载(Onload事件)
  • *不利于搜索引擎优化;

若是须要使用iframe,最好是经过javascript 动态给iframe添加src属性值,这样能够绕开以上两个问题。

六、如何实现浏览器内多个标签页之间的通讯? (阿里)

  • WebSocket、SharedWorker;
  • 也能够调用localstorge、cookies等本地存储方式;

localstorge另外一个浏览上下文里被添加、修改或删除时,它都会触发一个事件 storage

 

七、CSS3有哪些新特性?

  • 圆角 (border-radius:8px)
  • 阴影 (Shadow\Reflect)
  • 文字特效 (text-shadow、) 
  • 线性渐变 (gradient)
  • 旋转 (transform) 缩放,定位,动画等,例如:transform:\scale(0.85,0.90)\ translate(0px,-30px)\ skew(-9deg,0deg)\Animation:

 

  

2、构建工具

一、Webpack热更新实现原理

  1. 修改页面代码后,Webpack 监听到文件修改后,开始编译,编译完成后,发送消息给客户端
  2. 客户端获取到hash,成功后客户端构造hot-update.js script连接,而后插入主文档
  3. hot-update.js 插入成功后,执行hotAPI 的 createRecord 和 reload方法,获取到 Vue 组件的 render方法,从新 render 组件, 继而实现 UI 无刷新更新

二、减小 Webpack 打包时间

  •  首先咱们能够优化 Loader 的文件搜索范围,只在 src 文件夹下查找编译的 js 文件,排除 node_modules 中的文件,固然这样作还不够,咱们还能够将 Babel 编译过的文件缓存起来
loader: 'babel-loader?cacheDirectory=true'
  • HappyPack 能够将 Loader 的同步执行转换为并行的
  • DllPlugin 能够将特定的类库提早打包而后引入
  • 代码压缩
  • 若是你肯定一个文件下没有其余依赖,就可使用该 module.noParse 让 Webpack 不扫描该文件,这种方式对于大型的类库颇有帮助

三、减小 Webpack 打包后的文件体积

  • 按需加载
  • Scope Hoisting 会分析出模块之间的依赖关系,尽量的把打包出来的模块合并到一个函数中去
  • Tree Shaking 能够实现删除项目中未被引用的代码

3、框架原理

一、描述一下React 生命周期

渲染过程调用到的生命周期函数,主要几个要知道;
  	* constructor

  	* getInitialState

  	* getDefaultProps

  	* componentWillMount

  	* render

  	* componentDidMount


  	更新过程

  	* componentWillReceiveProps

  	* shouldComponentUpdate

  	* componentWillUpdate

  	* render

  	* componentDidUpdate


  	卸载过程

  	componentWillUnmount

二、实现组件有哪些方式?

  • React.createClass 使用API来定义组件 React ES6 class component 用 ES6 的class 来定义组件 Functional stateless component 经过函数定义无状态组件

三、应该在React生命周期的什么阶段发出ajax请求,为何?

  • AJAX请求应在 componentDidMount函数 进行请求。由于此时组件已经挂载安装,保证了数据更新后对应的组件也能更新

四、当组件的setState函数被调用以后,发生了什么?

  • React 会将传入的参数与组件当前的状态合并,生成新的状态 一> 根据新的状态构建 React 元素树 一> 计算出新的树与老树的节点差别,进行最小化重渲染

五、为何循环产生的组件中要利用上key这个特殊的prop?

  • Keys负责帮助React跟踪列表中哪些元素被改变/添加/移除。React利用子元素的key在比较新旧元素树的时候,快速得知一个元素是新的仍是刚刚被移除。 

六、介绍redux,主要解决什么问题

  •   是管理应用程序状态的库,解决数据管理和数据通讯的问题
  •   view 发出一个 action —> 派发器接收 action —> 让 store 进行数据更新:reducer 进行 state 操做 —> view 经过 store 提供的 getState 获取最新的数据  

七、redux 有什么缺点

  • 一个组件所须要的数据,必须由父组件传过来,而不能像 flux 中直接从 store 取。

  • 当一个组件相关数据更新时,即便父组件不须要用到这个组件,父组件仍是会从新 render,可能会有效率影响,或者须要写复杂的 shouldComponentUpdate 进行判断。

八、为何虚拟 dom 会提升性能?(必考)

  • 虚拟 dom 至关于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操做,从而提升性能。

九、react diff 原理(常考,大厂必考)

  • 把树形结构按照层级分解,只比较同级元素。

  • 给列表结构的每一个单元添加惟一的 key 属性,方便比较。

  • 合并操做,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每个事件循环结束, React 检查全部标记 dirty 的 component 从新绘制.

  • 选择性子树渲染。开发人员能够重写 shouldComponentUpdate 提升 diff 的性能

八、介绍react优化

  1. 用 shouldComponentUpdate 避免资源浪费 
  2. 复杂的页面不要在一个组件里面写完。
  3. 请尽可能使用const element
  4. map里面添加key,而且key不要使用index(可变的)。具体可参考使用Perf工具研究React Key对渲染的影响
  5. 尽可能少用setTimeOut或不可控的refs、DOM操做。
  6. propsstate的数据尽量简单明了,扁平化。
  7. 使用return null而不是CSS的display:none来控制节点的显示隐藏。保证同一时间页面的DOM节点尽量的少

4、性能优化

0、在开发项目上,知道那些优化的方式

  • 性能优化:减小 http 请求数、避免跳转重定向、压缩代码图片、减小DOM操做、避免全局变量、将样式表放在顶部,将脚本放在底部、小图片(<10kb)转换base64编码、资源按需加载等。
  • 代码优化:有意义的命名,适当的注释,代码逻辑清晰,避免巨大函数,避免对象强耦合、使用事件代理、函数节流和防抖、禁止全局变量防止内存泄漏等。

一、函数节流和防抖

  • debounce:把触发很是频繁的事件(好比按键搜索)合并成一次执行。

  • throttle:保证每 X 毫秒恒定的执行次数,好比每200ms检查下滚动位置,并触发 CSS 动画或请求数据。

  • requestAnimationFrame:可替代 throttle ,函数须要从新计算和渲染屏幕上的元素时,想保证动画或变化的平滑性,能够用它。注意:IE9 不支持。

  requestAnimationFrame优势

  • 动画保持 60fps(每一帧 16 ms),浏览器内部决定渲染的最佳时机
  • 简洁标准的 API,后期维护成本低
  • 浏览器标签未激活时,一切都不会执行

查看示例

二、介绍事件代理以及优缺点

在js中,当咱们移除某个元素但没有将元素和监听函数进行解绑时,事件处理函数依旧会留在内存中,没法被当成垃圾回收。

  1. 减小事件注册,节省内存
  2. 减小了dom节点更新的操做,处理逻辑只需在委托元素上进行
  3. 缺点:事件委托基于冒泡,对于onfoucs和onblur等事件不支持;层级过多,冒泡过程当中,可能会被某层阻止掉

三、手写原生js实现事件代理,并要求兼容浏览器

  • 其实就是考核对事件对象e的了解程度,以及在IE下对应的属性名
  • addEventListener、attachEvent
  • e.target、e.srcElement
    function delegateEvent(interfaceEle, selector, type, fn) {
    
        if(interfaceEle.addEventListener){
        interfaceEle.addEventListener(type, eventfn);
        }else{
        interfaceEle.attachEvent("on"+type, eventfn);
        }
         
        function eventfn(e){
            var e = e || window.event;    
            var target = e.target || e.srcElement;
            //若是目标元素与选择器匹配则执行函数
            if (matchSelector(target, selector)) {
                if(fn) {
                     //将fn内部的this指向target(在此以前this都是指向的绑定事件的元素即interfaceEle)
                    fn.call(target, e); 
                }
            }
        }
    }

     

四、React组件事件代理的原理、事件处理过程

  • 并不是 #child 和 #parent 的事件分别代理到 document 上,而是 React 在 document 上绑定了一个 dispatchEvent 函数(事件),在执行 dispatchEvent 的过程当中,其内部会依次执行 #child 和 #parent 上绑定的事件。
  • React 合成事件对象的e.stopPropagation,只能阻止 React 模拟的事件冒泡,并不能阻止真实的 DOM 事件冒泡,更加不能阻止已经触发元素的多个事件的依次执行。在这种状况下,只有原生事件对象的 stopImmediatePropagation能作到。
  • 事件处理过程:事件处理过程
  • 示例

 五、什么是内存泄漏?

本质上,内存泄漏能够定义为:应用程序再也不须要占用内存的时候,因为某些缘由,内存没有被操做系统或可用内存池回收

因此,确保用完之后把它设置为 null 或者从新定义

  三种类型的常见 JavaScript 内存泄漏

六、PWA:Workbox

 

 

5、算法、设计模式

前端架构主要解决的是高复用性,架构能力提高方向主要是组件库开发、前端框架实现

 一、观察者和订阅-发布的区别,各自用在哪里

  • 观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有经过消息代理进行通讯。

  • 发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。

  • 观察者模式大多数时候是同步的,好比当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)。

  • 观察者设计模式定义了对象间的一种一对多的组合关系,以便一个对象的状态发生变化时,全部依赖于它的对象都获得通知并自动刷新
  • 示例

6、网络安全、通讯协议

一、HTTP2.0和HTTP1.X相比的新特性

  1. 新的二进制格式,相对文原本说有更强的健壮性
  2. 多路复用(MultiPlexing),即链接共享。一个链接上能够有多个request,一个request对应一个id 。
  3. header压缩:HTTP1.x的header带有大量信息,并且每次都要重复发送,HTTP2.0使用encoder来减小须要传输的header大小,通信双方各自cache一份header fields表,既避免了重复header的传输,又减少了须要传输的大小。
  4. 服务端推送(server push)

二、经过什么作到并发请求

对请求并发数进行限制,而且使用排队机制让请求有序的发送出去

三、http1.1时如何复用tcp链接

  使用 keep-alive

四、三次握手、四次挥手

 

  1. 客户端向服务器发送一个 SYN(synchronize:同步) 包,请求创建链接
  2. 服务器收到后会发一个对SYN包的确认包ACK (Acknowledgement)便是确认字符回去
  3. 客户端发送一个确认包(ACK),通知服务器链接已创建

客户端发送FIN报文,没有数据要发给你了

 五、什么是 XSS 攻击?如何防范 XSS 攻击?什么是 CSP?

Cross-Site Scripting(跨站脚本攻击)简称 XSS,是一种代码注入攻击。攻击者经过注入恶意脚本,使之在用户的浏览器上运行

解决方法:

  • 转义字符
  • CSP 本质上就是创建白名单,开发者明确告诉浏览器哪些外部资源能够加载和执行

什么是 CSP(Content-Security-Policy) ?

内容安全策略 (CSP)  本质上就是创建白名单,开发者明确告诉浏览器哪些外部资源能够加载和执行

一般能够经过两种方式来开启 CSP:

  1. 设置 HTTP Header 中的 Content-Security-Policy
  2. 设置 meta 标签的方式 <meta http-equiv="Content-Security-Policy">

示例:

  • 只容许加载本站资源

    Content-Security-Policy: default-src ‘self’ 
  • 只容许加载 HTTPS 协议图片

    Content-Security-Policy: img-src https://*
  1. 【XSS】 美团

六、什么是 CSRF 攻击?如何防范 CSRF 攻击?

CSRF(Cross-site request forgery)跨站请求伪造:冒充用户执行某项操做的目的

  • CSRF自动防护策略:同源检测(Origin 和 Referer 验证)。
  • CSRF主动防护措施:Token验证 或者 双重Cookie验证 以及配合Samesite Cookie。
  • 保证页面的幂等性,后端接口不要在GET页面中作用户操做。

示例:

2007年Gmail的CSRF漏洞:点开一个黑客的连接,全部邮件都被窃取(攻击者诱导用户进入某个页面,在页面中经过表单提交 POST 请求,也说明了表单是能够进行跨域攻击的)

2008年YouTube上几乎全部用户能够操做的动做都存在CSRF漏洞

2012年WordPress发现了一个操做用户帐户的CSRF漏洞:攻击者引导用户先进入目标的WordPress,而后点击其钓鱼站点上的某个按钮,该按钮其实是表单提交按钮,会添加某个具备管理员权限的用户

七、什么是点击劫持?如何防范点击劫持?

点击劫持是一种视觉欺骗的攻击手段。攻击者将须要攻击的网站经过 iframe 嵌套的方式嵌入本身的网页中,并将 iframe 设置为透明,在页面中透出一个按钮诱导用户点击。

X-FRAME-OPTIONS 是一个 HTTP 响应头,在现代浏览器有一个很好的支持。这个 HTTP 响应头 就是为了防护用 iframe 嵌套的点击劫持攻击。

  • DENY,表示页面不容许经过 iframe 的方式展现
  • SAMEORIGIN,表示页面能够在相同域名下经过 iframe 的方式展现
  • ALLOW-FROM,表示页面能够在指定来源的 iframe 中展现

八、什么是中间人攻击?如何防范中间人攻击?

中间人攻击是攻击方同时与服务端和客户端创建起了链接,并让对方认为链接是安全的,可是实际上整个通讯过程都被攻击者控制了。攻击者不只能得到双方的通讯信息,还能修改通讯信息。如:不安全的公共 WIFI

 九、URI 与 URL 的区别

  • URI:统一资源标志符
  • URL:统一资源定位符
  • URN:URN 是另外一种形式的 URI,它经过特定命名空间中的惟一名称来标识资源,好比 ISBN 版本号,urn:isbn:9780141036144
  • URI 包括不少协议,如 HTTPS、data、URN 等等,因此 URL 和 URN 都是 URI 的子集

 

6、监控

一、页面埋点

  • 手动埋点:灵活性高,但工做量大
  • 自动埋点:灵活性低,统计全部的事件而且定时上报,但工做量小

二、性能监控

只须要调用 performance.getEntriesByType('navigation') ,就能够得到页面中各类详细的性能相关信息

三、异常监控

  • 一般的办法是使用 window.onerror 拦截报错
  • 对于跨域的代码运行错误会显示 Script error. 对于这种状况咱们须要给 script 标签添加 crossorigin 属性
  • 对于异步代码来讲,可使用 catch 的方式捕获错误。好比 Promise 能够直接使用 catch 函数,async await 可使用 try catch

script标签的crossorigin属性

crossorigin的属性值能够是anonymoususe-credentials,会被浏览器默认作anonymous。crossorigin的做用有三个:

  1. crossorigin会让浏览器启用CORS访问检查,检查http相应头的Access-Control-Allow-Origin
  2. 对于传统script须要跨域获取的js资源,控制暴露出其报错的详细信息
  3. 对于module script,控制用于跨域请求的凭据模式

script标签的integrity属性

<script crossorigin="anonymous" integrity="sha256-PJJrxrJLzT6CCz1jDfQXTRWOO9zmemDQbmLtSlFQluc=" src="https://assets-cdn.github.com/assets/frameworks-3c926bc6b24bcd3e820b3d630df4174d158e3bdce67a60d06e62ed4a515096e7.js"></script>

这是github源码, integrity 告诉浏览器,使用sha256签名算法对下载的js文件进行计算,并与intergrity提供的摘要签名对比,若是两者不一致,就不会执行这个资源。

  • 减小由【托管在CDN的资源被篡改】而引入的XSS 风险
  • 减小通讯过程资源被篡改而引入的XSS风险(同时使用https会更保险

script标签的asyncdefer 属性

  • async 仅适用于外链,规定脚本异步执行:不会按照出现的顺序执行,执行的时候,有可能页面还没解析完成,不会阻塞页面解析
  • defer仅适用于外链,规定脚本延迟执行:会按照出现的顺序执行,在html解析完成后, DOMContentLoaded以前执行,不会阻塞页面解析

 

相关文章
相关标签/搜索