BING
斯是陋室,唯吾芳馨
原创

一句话的事

共 12,620 字,需阅读 32 分钟2017/05/02 下午7,708 次阅读

Web 开发较复杂,因为涉及的面比较多且分散,但大部分都是一句话能说完的事。

希望可以刀刀见血,招招致命。

#HTML 篇

#一句话介绍 HTML5

语义化标签,识别性更高、利于 SEO 和开发过程;

新能力:Video、Audio、Canvas...

#CSS 篇

#清除浮动的方法

  • clear 属性: left、right、both
  • overflow:hidden

#overflow: hidden 为什么能清除浮动

overflow:hidden 本意是溢出隐藏,但浏览器需要知道该显示多少才能隐藏剩下的,默认高度又是 auto,所以浮动的元素都会被计算为父元素的高度,顺带就实现了清除浮动的目的。

副作用:脱离文档流的元素,超出部分可能会被隐藏。

#如何快速实现绝对居中

  • flex
  • 绝对定位 + transform

#实现一个 DOM 移动的动画

  • CSS3 transition + transform(translate) 使用 GPU 渲染位移
  • CSS animate
  • DOM JavaScript 定时器设置边距属性

#content-boxborder-box 的区别

  • content-box 默认值,W3C 标准盒模型,不包含边框和内边距
  • border-box 原 IE 模型,包含边框和内边距

默认 content-box,可通过 box-sizing 指定。

#浏览器篇

#了解解释器的 GC 机制否

垃圾标记

  • 执行标记:变量进入执行上下文和执行完上下文都分别有标记
  • 引用计数:底层计算变量被引用了几次,为 0 则释放(Python 目前也如此)

垃圾回收

  • 周期回收:类似内存监听/拦截,比如隔多久事件回收一次,内存使用率超多少回收一次
  • 阈值回收:早期 IE 的 GC 机制,比如变量超过多少个就执行回收
  • 动态阈值回收:IE7 中对 IE 本身 GC 的优化,阈值根据内存占用率和规律来确定,效果很好
  • 增量回收:Chrome 中的机制,因为 GC 会产生不同时间的线程阻塞,所以不能一次处理太多,要分批次回收
  • 优化回收:回收内存后,可能会出现内存碎片(不连贯),所以回收同时进行整理

#Web 缓存

  • Cache-Control 指定过期时间、缓存状态、选项,优先级高于 Expires
  • Expires 1.0 协议中的头,指定缓存过期时间
  • Last-modified 服务端资源最后变更时间,若资源未变更会返回 304
  • If-Modified-Since 向服务端请求本地资源和远程资源的一致性(判断修改时间)
  • If-None-Match 向服务端请求本地资源和远程资源的一致性(判断 hash 值)
  • ETag 标识资源状态的随机串
    • Last-modified 标注的修改时间只能精确到秒级,是以时间为单位,一秒内修改多次的话就无法判断了
    • 避免定期生成的文件却无变动的文件因为 Last-modified 字段而频繁被更新
    • Last-modified 的时间会受生产环境(服务器、代理服务器)影响,不是百分百准确

真实生产中推荐使用 ETag,同时也可以与 Last-modified 一同使用,浏览器会优先验证 ETag,才会继续比对 Last-Modified,最后才决定是否返回 304。

#常见 Content-Type

  • text/*
  • audio/*
  • image/*
  • video/*
  • application/*
  • ...

#JavaScript 篇

#var let const 的区别

  • var 作用域声明置顶,只有全局、函数两种作用域
  • let 不置顶,大括号为作用域、块级作用域
  • const 声明必须赋值,指针不可变,引用数据可变

#引用数据类型和基本数据类型的区别

引用类型的数据被重新引用时不会复制数据,而是将指针指向之前的数据地址。

  • Stack 栈:存放基本类型数据和引用类型数据的指针
  • Heap 堆:存放被引用的引用类型数据

如果一个值是引用类型的,那么它的存储空间将从堆中分配。由于引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。 相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。

#undefinednull 的区别

基本同义,但不完全同义。

由于运算中的隐式转换会导致,null 被转为 0,无法捕获错误节点,于是诞生了 undefined

  • null 原始类型 Null 的唯一值,表示:空数据,转为数字时为 NaN
  • undefined 原始类型 Undefined 的唯一值,派生自 Null 类型,表示:缺少值(与预期不符),转为数字时为 0

#ES6 的新特性

  • 新 API,比如各种对象的扩展(数组、对象、字符串、函数...)
  • 解构、扩展运算符
  • 新数据类型,Set(类似于数学中的集合,可进行成员关系测试(交、差、并、补集)、去重)、Symbol...
  • Proxy 代理对象
  • Promise 异步对象,可以返回一个 Promise 进行链式分解、组合
  • Iterator 迭代器
  • Generator 生成器
  • async await 同步阻塞
  • Class 代替构造函数,可继承
  • 装饰器 Decorator
  • 统一的模块规范

#浏览器若支持 module,会带来哪些便利

  • 统一了当然爽
  • 不再需要 UMD 了(通用加载模块)
  • 能像 Python 一样不再需要对象作为命名空间,如 Math 这样的

#回调地狱怎么解决

  • 合理的封装和抽象
  • Promise:可组合、可链式(平级)分解
  • async await:终极大杀器,"同步阻塞",C# 里的东西

#为啥会有闭包,有何用

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

  • 可以读取函数内部的变量
  • 让这些变量的值始终保持在内存中

缺陷:

  • DOM 循环引用可能会内存泄漏(老版本 IE)
  • 内存常驻

#作用域的尽头是哪

尽头应该指向全局 window global,作用域的本质是就近原则,即访问作用路链最近的数据。

#This 是啥

当前执行上下文环境。

#深拷贝方法

  • 序列化
  • 递归
          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
var cloneObj = function (obj) { var str, newobj = obj.constructor === Array ? [] : {}; if (typeof obj !== "object") { return; } else if (window.JSON) { (str = JSON.stringify(obj)), //系列化对象 (newobj = JSON.parse(str)); //还原 } else { for (var i in obj) { newobj[i] = typeof obj[i] === "object" ? cloneObj(obj[i]) : obj[i]; } } return newobj; };

#正则常用含义

  • ^ 匹配开头
  • $ 匹配结尾
  • * 匹配前面元字符 0 次或多次
  • + 匹配前面元字符 1 次或多次
  • ? 匹配前面元字符 0 次或 1 次
  • (x) 匹配 x 保存 x 在名为$1...$9 的变量中
  • x|y 匹配 x 或 y
  • {n} 精确匹配 n 次
  • {n,} 匹配 n 次以上
  • {n,m} 匹配 n-m 次
  • [xyz] 字符集(character set),匹配这个集合中的任一一个字符(或元字符)
  • [^xyz] 不匹配这个集合中的任何一个字符

#事件机制和代理/委托

  • IE:冒泡,由子到父
  • Netscape:捕获,由父到子
  • W3C 标准:捕获 > 冒泡,由父到子 > 由子到父

stopPropagation 停止事件传播,preventDefault 阻止默认事件。

addEventListener 第三参数用于指定事件传播过程,true 表示使用捕获机制,false 为冒泡机制。

事件委托一句话:普遍节点事件委托给父节点,节省内存、便于管理。

#__proto__prototype 的区别和关系

本质没有关系。

__proto__ 原型链,指向对象的构造函数原型/类

prototype 原型属性(只有 function 具有),指向函数对象对应的原型/类(的可继承属性对象)

共同目的:为了实现属性/方法的继承和共享。

两者区别:prototype 实现了属性/方法数据的共享,__proto__ 实现了属性的多级继承。

唯一关系:就近原则,找实例的方法会读取 prototype,没有的话就会延原型链向上查找。

#ES6 与 ES5 中继承的区别?

本质上没有区别,细节上有区别。

#ES5

将子类构造函数的原型设置为父类构造函数的实例。

示例:

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
function Super() {} function Sub() {} Sub.prototype = new Super(); Sub.prototype.constructor = Sub; const sub = new Sub(); Sub.prototype.constructor === Sub; // ② true sub.constructor === Sub; // ④ true sub.__proto__ === Sub.prototype; // ⑤ true Sub.prototype.__proto__ == Super.prototype; // ⑦ true

缺陷:无法私有化属性/方法,会污染原型属性,可能需要组合继承进行优化。

#ES6

形式上:使用 class 中的 extends 关键字进行继承,通过 constructor 定义构造函数,用 super 调用父类的属性方法;

本质上:依旧使用原型 + 原型链实现继承。

不同点:两条继承链:一条实现构造函数的继承,一条实现原型的继承。

          
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
class Super {} class Sub extends Super {} const sub = new Sub(); Sub.prototype.constructor === Sub; // ② true sub.constructor === Sub; // ④ true sub.__proto__ === Sub.prototype; // ⑤ true Sub.__proto__ === Super; // ⑥ true Sub.prototype.__proto__ === Super.prototype; // ⑦ true

#目前 JavaScript 栈已实现的模块化有哪些,有何区别

规范 来源 实现 特征
CommonJS CommonJS Node.js 文件为单位、局部作用域、可缓存、同步、按顺序加载
AMD RequireJS require.js、curl.js 异步加载、依赖前置、提前执行、API 一夫多用
CMD SeaJS sea.js 异步加载、依赖就近、延迟执行、API 职责单一
UMD 通用规范 通用 跨平台、判断环境来输出不同模块

#脚本阻塞的解决方法

  • 放置在 </body>
  • async 加载和渲染并行执行、异步、会乱序;适合 DOM 无关、无依赖的脚本
  • defer 并行加载、当 DOM 渲染后 DOMContentLoaded 执行前执行、异步、不会乱序

#使用 JavaScript 测试网络状态

  • navigator.onLine(只能测试本机是否连接局域网)
  • ajax
  • image or iframe 监听 onerror

#封装、继承、多态、重载

  • 封装:恩,就是封装
  • 继承:构造函数、原型、原型链、类
  • 重载:指允许存在多个同名方法,而这些方法的参数不同(原:编译器)
  • 多态:在 JavaScript 中继承(覆盖)和重载(参数判断)都是模拟多态的表现形式

#继承

阮一峰 - JavaScript 继承机制的设计思想

#多态 & 重载

多态和重载的区别在于编译器何时去寻找所要调用的具体方法; 对于重载,在方法调用之前,编译器就已经确定了所要调用的方法,这称为 “早绑定” 或 “静态绑定”; 对于多态,只有等到方法调用的那一刻,编译器才会确定所要调用的具体方法,这称为 “晚绑定” 或 “动态绑定”。

在 JavaScript 中继承和重载都是模拟多态的表现形式。

#元素节点、文本节点、属性节点还记得是啥东西

都是 DOM 树的抽象,共同特征有:

  • nodeName(节点名称)
  • nodeValue(节点值)
  • nodeType(节点类型)

其实还有一些其他的节点类型:

  • 1:元素(ELEMENT_NODE)
  • 2:属性(ATTRIBUTE_NODE)
  • 3:文本(TEXT_NODE)
  • 8:注释(COMMENT_NODE)
  • 9:文档(DOCUMENT_NODE)

更多在这

#框架篇

#Vue 双向数据绑定的实现

本质是使用 ES6 中的 Object.defineProperty 方法实现,该方法定义对对象的描述;从而用它可以实现一个类似读写拦截器的机制; 同时使用观察者模式维护一个订阅者列表,当数据发生对应变化时,则执行订阅者对应的方法,如:操作 DOM。

Vue1 和 Vue2 的最大区别是使用了 virtual DOM。

angular.js 1.x 中使用脏检查,脏检查:封装所有可封装的事件,每次发生任何事件,进行大检查,不超过 10 次,不低于 2 次。

也有纯粹使用观察者模式的,像:backbone.js。

#React、Vue、Angular(> 2.x) 的不同

定位:

React、Vue 本身是 UI 框架,更多功能都需要扩展来实现,都可以实现从小到大的各类应用,也能支持各种模板语言或 TS 这样的编程语言开发,也都支持完备的测试机制。

Angular 更倾向于一个 platform 开发框架,具有自身完备的路由、数据、平台兼容等各模块。

实现:

  • Virtual DOM:React 和 Vue 很类似,都使用了 Virtual DOM;但 diff 算法不同,React 使用同级比较,且有时候需要手动执行 diff,Vue 做了很多的优化,比如自动缓存静态 Class 那一类的优化
  • 模板语法:React 倾向于 All in js 所以模板用 jsx,Vue 使用 webpack 对应的解析器支持了 HTML 作为组件模板,更容易上手,且和 Web components 很像,真正用到 Web components 的是 Angular 的 ViewEncapsulation.Native
  • 开发模式:React 严格上只针对 MVC 的 View 层,Vue 则是 MVVM 模式的一种实现
  • 数据更新:
    • Vue 采用依赖追踪,默认就是优化状态:有多少数据变动,就会触发多少更新,不多也不少。
    • React 可以手动添加 shouldComponentUpdate 来避免不需要的 re-render
  • 数据管理:React 和 Vue 的单向数据流管理机制也非常类似,React 有 Redux,Vue 有 Vuex,但 Vue 本身提供了双向数据绑定;Angular 则使用 RxJS 来实践数据管理,也可以转为 Promose 哈;Angular 使用强类型 TS 作为母语,有内置的强壮的模块来实现各种需求

共同点: 目前三者的社区热度都很火热,生态链也很完善,都是相对成熟的技术栈。越来越趋于同质化,在 Web components 真正成熟之前,各种框架都在探索一种类似的组件抽象机制; 同时都期望框架不单单是实现 Web 端的应用开发,Angular 可以和 nativescript 开发原生客户端应用,Vue 有 Weex 解决方案,React 更有火遍全地球的 react-native 框架; Angular 本身支持 SSR,React 有 Next.js,Vue 有 Nuxt.js。

本质:

框架本身只是工具,只是为了我们更快搭建应用诞生的,没有谁最好谁不好,选择适合的最好,为了追新而实践是一定一定要避免的。

#工具篇

#Grunt、Gulp、Webpack 区别

Grunt、Gulp 应该可以称之为自动化工具,他可以自动化地帮我们处理对特定资源/事件的处理,其实在这两者出现之前,很多有条件的团队一直在实践一些基于 Python、Java、PHP 的工具来完成这些事。

Webpack 是一个基于 Node.js 的资源处理工具,更像一个平台或中介者,我们可以基于它配置各种插件扩展用于处理不同的文件资源,并做出相应输出,可能是编译、分包、压缩、Lint...

非要比喻的话:Grunt / Gulp 像两条流水线组;Webpack 则像一个工厂,不仅有流水线,还有自己的仓储、销售、生产管理等各个部门。

  • Grunt 是以任务形式处理执行,早期的各种插件可能都需要进行 IO 操作,性能不佳
  • Gulp 也是任务形式,但更灵活,实际工作时以文件流为处理形式,无论是内存中还是语法上
  • Webpack 是以 [原始工程 > modules > 生产资源] 的形式处理资源 + 基于 Node.js 的扩展机制来管理工程,更倾向于对整个开发系统的管理

#Webpack 打包速度慢,可能什么原因

  • 用了不必要的插件
  • 公共库/框架/包没有合理抽离
  • Babel 对已压缩的包进行了再次编译

#扩展篇

#跨域通信方案

  • JSONP
  • 反代
  • CORS

#XSS 和 CSRF 怎么解决

  • XSS:永远不相信用户输入的,做好各个节点的过滤
  • CSRF:SPA 下用 JWT + Localstorage,非 SPA 使用一次性令牌验证

#Koa 有啥不一样

核心是对 http 模块的封装。

  • 1.0: 使用 generator 封装成了中间件机制
  • 2.0: 完全使用 Promise 并配合 async 来实现异步

#HTTP 状态码了解

  • 2xx 正常
  • 3xx 重定向(304 缓存除外)301 永久跳转、302 临时跳转
  • 4xx 请求错误
  • 5xx 服务端异常

#Node.js 中的 Stream 和 Buffer

  • Stream,流,对数据处理形式的抽象
  • Buffer,缓冲区,将二进制数据单独存储在 V8 堆内存之外的原始内存区域,数据类似整数数组

#iframe/多窗口通信

  • postmessage / onmessage
  • window.name

#HTML 编码解码

主要做的事:将 HTML 标签解析为转义符,或将转移符解析为标签。

#浏览器多页面通信

  • localstorge
  • sessionstorage
  • cookies
  • SharedWorker 多个页面共享线程

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

#cookie 和 session 的联系和区别

  • Session 是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在内存、数据库、文件中。
  • Cookie 是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现 Session 的一种方式。

#RESTful 是啥?GETPOST 的本质区别

一句话:URL 仅代表资源,HTTP 请求类型来描述行为。

本质上,GET 就是请求,且 URL 的长度有限制,一般在 2k 之内; POST 就是发送数据,以 body 为数据宿主,常见类型有:application/json xml text formData 等; PUT 用于全量修改,PATCH 用于单量修改,DELETE 按照标准是不支持 body 的,但大部分浏览器和服务端都兼容实现了,但在代理情况下,数据可能会丢失。

#Web Components 是什么

Web Components 是一个抽象概念,按照 MDN 的解释(Web Components),包含下面 4 个技术体系:

  1. Custom Elements

类似:几乎所有框架的组件机制

  1. HTML Templates

即,模板片段,HTML <template> 元素是一种保存客户端内容的机制,在加载页面时不会呈现,但可能随后在运行时使用 JavaScript 实例化。

  1. Shadow DOM

内容区隔离

  1. HTML Imports

可以通过 HTML link 导入 Html

#底层篇

#算法复杂度的概念

算法在编写成可执行程序后,运行时所需要的资源,资源包括时间资源和内存资源。

一般称之为:时间复杂度和空间复杂度。

如:

  • 循环一次 = n
  • 循环两次 = 2n(n)
  • 嵌套两层循环 = n²
  • ...

#URL 从输入到展现的过程

浏览器 DNS 缓存 > 本机 DNS 缓存 > LDNS(NS) > RDNS(GTLD) > NS(IP) > IP

#HTTPS

简单粗暴系列之 HTTPS 原理

简单说:将数据进行对称/非对称加密后进行传输。

SSL (Secure Sockets Layer) 由网景公司开发,3.0 后被 ISOC 接管升级为 TLS。

  • 握手阶段:客户端向服务器端索要并验证公钥,双方协商生成"对话密钥",共进行四次明文通信
  • 通信阶段:双方采用"对话密钥"进行加密通信

#OSI 七层网络模型

  • 第 7 层:应用层(Application Layer),如:HTTP,HTTPS,FTP,TELNET,SSH,SMTP,POP3...
  • 第 6 层:表示层(Presentation Layer),如:HTTP、FTP、Telnet...
  • 第 5 层:会话层(Session Layer),如:RPC、PAP、H.245...
  • 第 4 层:传输层(Transport Layer),如:TCP/IP 协议、UDP 协议...
  • 第 3 层:网络层(Network Layer),如:路由器、交换机
  • 第 2 层:数据链接层(Data Link Layer) ,如:以太网、Wi-Fi、GPRS
  • 第 1 层:物理层(Physical Layer),如:针脚、电压、线缆、集线器、中继器、网卡、主机适配器

#TCP/IP、HTTP、Socket 的区别?

本质上压根没关系。

  • TCP/IP:传输层协议,定义数据如何在网络中传输
  • HTTP:应用层协议,定义如何包装数据,Web 使用 HTTP 协议作应用层协议,以封装 HTTP 文本信息
  • Socket:非协议,更像一种标准、一种能力,一种对 TCP/IP 进行封装后可以进行全双工通信的能力;在 Web 中 WebSocket 是一种协议,需要使用 HTTP 发起 “握手” 来建立连接

#HTTP2 有哪些不一样

#多路复用 (Multiplexing)

多路复用允许同时通过单一的 HTTP/2 连接发起多重的请求-响应消息,在 HTTP1.1 中「浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制。超过限制数目的请求会被阻塞」。

#二进制分帧

HTTP2 在 应用层(HTTP/2)和传输层(TCP / UDP)之间增加一个二进制分帧层。

在二进制分帧层中, HTTP/2 会将所有传输的信息分割为更小的消息和帧(frame),并对它们采用二进制格式的编码,其中 HTTP1.x 的首部信息会被封装到 header frame,而相应的 Request Body 则封装到 data frame 里面。

#首部压缩(Header Compression)

使用 HPACK 算法将重复的、多余的、正常的头部信息进行压缩处理。

#服务端推送(Server Push)

简单说:当一个客户端请求资源 X,而服务器知道它很可能也需要资源 Z 的情况下,服务器可以在客户端发送请求前,主动将资源 Z 推送给客户端。

#负载均衡

负责均衡的具体就是让每一层在访问自己的上游层时做到计算单元分配最大均匀化。

负责均衡有多个层面:

  • 客户层:client,由 “DNS-server 轮询” 实现 “client > IP” 的分配
  • 反代层:nginx,由 “upstream(默认轮询)” 实现 “request > Web server” 的分配
  • 站点层:Web server,由 “服务连接池” 实现对服务层访问的分配
  • 服务层:Service,需平衡 “数据均衡” 与 “请求均衡” 两个点
  • 数据层:Database/cache

相关: 一分钟了解负载均衡的一切

#如何保证程序的健壮性

  • 灰度发布:一次只向一部分用户发布功能,比较强大的如 Facebook,可以向特定年龄,文化,时间段的用户发布。比如弱的,也可以向特定的 IP 发布。
  • 监控服务:Core Dump 监控、Log 监控、CPU 监控、内存监控...
  • 容灾措施:XXX

#思考篇

#学习方法

根据大致目录简历思维大导图,构建知识图谱,主要靠文档,然后实践。

#对新技术的看法和了解渠道

掘金、V 站、开源中国,必须了解、及时学习、按需实践,绝不为了实践而实践,也不过于被动保守避免重构升级。

#任意连续的三个正整数相乘,一定能被 6 整除吗,为什么

因为三个连续的正整数中必有一个能被 3 整除,还有一个能被 2 整除.所以必能被 6 整除。

未完

署名 - 非商业性使用 4.0 国际 https://surmon.me/article/51
5 / 5 条看法
访客身份
在下有一拙见,不知...
  • 影
    🇨🇳CNHangzhouMac OSChrome

    border-box:IE 模型,不包含边框和内边距 content-box:默认值,W3C 标准,包含边框和内边距 

    这里说反了吧,border-box 是包含 border 和 padding 才对。

    • Surmon
      Surmon🇨🇳CNShanghaiMac OSChrome

      回复

      MDN box-sizing  你说得对,我改。

  • 1
    1🇨🇳CNGuangzhouWindowsChrome

    👏

  • zhutou3ge
    Zhutou3ge🇨🇳CNBeijingiOSMobile Safari

    发现一个小问题你的站点在MacBook Pro下谷歌浏览器打开发热有点严重,浏览器切换成手机模式发热现象就没有了。我的猜测应该是pc版首页的背景循环的问题👍👍

    • Surmon
      Surmon🇨🇳CNXi'anMac OSChrome

      回复

      猜测正确😃,但背景动画用的是 particles.js ,没有太大优化空间,我可能在后期增加一个关闭动画的功能