题目概览
- 浏览器内多个标签页之间的通信方式有哪些
- 简述下你理解的优雅降级和渐进增强
- 写一个判断数据类型的方法
题目解答
浏览器内多个标签页之间的通信方式有哪些
- WebSocket(可跨域)
- postMessage(可跨域)
- SharedWorker
- Server-Sent Events
- localStorage
- BroadcastChannel IE不支持
- Cookies
简述下你理解的优雅降级和渐进增强
- 渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验;渐进增强的写法,优先考虑老版本浏览器的可用性,最后才考虑新版本的可用性。而在现在前缀CSS3和正常CSS3都可用的情况下,正常CSS3会覆盖前缀CSS3
- 优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后再针对低版本浏览器进行兼容。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览;优雅降级的写法,优先考虑新版本浏览器的可用性,最后才考虑老版本的可用性。而在现在前缀CSS3和正常CSS3都可用的情况下,前缀CSS3会覆盖正常的CSS3
- 如何选择:若低版本用户居多,则优先采用渐进增强的开发流程;若高版本用户居多,则为了提高大多数用户的使用体验,那当然优先采用优雅降级的开发流程;业务优先,提升用户体验永远不会排在最前面;最重要的还是保证尽可能多的用户可以正常访问网站,在此之后再考虑降级的极端情形和现代浏览器的体验增强
写一个判断数据类型的方法
-
简易写法
function type(obj) { return Object.prototype.toString.call(obj).replace(/[objects|]/g, ''); }
-
精细封装
/*支持 number, boolean, string, undefined, null, symbol array, object, set, weakset, map, weakmap function, class regexp, date, math, promise */ const _toString = Object.prototype.toString const NULL = 'null' const OBJECT = 'object' const NUMBER = 'number' const BOOLEAN = 'boolean' const STRING = 'string' const UNKNOW = 'unknow' /** * * @param {*} element 任意类型的变量 * @param {Boolean} strict [default: false] 是否为严格模式 * @return {String} 变量的真实类型 */ export default function type (element, strict = false) { strict = !!strict // #1 fix typeof null === 'object' if (element === null) { return NULL } const eleType = typeof element // #2 return [number string boolean undefined symbol] if (eleType !== OBJECT) { return eleType } let eleRealType let eleRealTypeLower try { eleRealType = _toString.call(element).slice(8, -1) eleRealTypeLower = eleRealType.toLowerCase() } catch (e) { // #3 IE activie 对象 return OBJECT } // #4 fix typeof new String('') === 'object' , expect 'string' if (eleRealTypeLower !== OBJECT) { // 严格模式下 会严格区分`number、string、boolean`的原始值和对象值 // example `new String('') => 'String'`、`String('') => 'string'` if (strict && (eleRealTypeLower === NUMBER || eleRealTypeLower === BOOLEAN || eleRealTypeLower === STRING)) { return eleRealType } return eleRealTypeLower } if (element.constructor == Object) { return eleRealTypeLower } // #5 Object.create(null) try { // __proto__ 为部分早期浏览器 if (Object.getPrototypeOf(element) === NULL || element.__proto__ === NULL) { return OBJECT } } catch (e) { // IE 无 Object.getPrototypeOf } // #6 function A () {}; new A try { const constructorName = element.constructor.name if (typeof constructorName === STRING) { return constructorName } } catch (e) { // No constructor } // function A() {}; A.prototype.constructor = null; new A return UNKNOW }