Web开发较复杂,因为设计的面比较多且分散,但大部分都是一句话能说完的事。
刀刀见血,招招致命。
Html篇
一句话介绍HTML5?
语义化标签,识别性更高、利于SEO;
新能力:Video、Audio、Canvas…
Css篇
清除浮动的方法?
clear
属性: left、right、bothoverflow:hidden
overflow: hidden
为什么能清除浮动?
overflow:hidden
,本意是溢出隐藏,但浏览器需要知道该显示多少才能隐藏剩下的,默认高度又是auto,所以浮动的元素都会被计算为父元素的高度,顺带就实现了清除浮动的目的。
副作用:元素过多时,可能会隐藏掉一部分。
如何快速实现绝对居中?
- flex
- 绝对定位 + 负外边距
实现一个Dom移动的动画:
- css3 transition + transform(translate) 使用 GPU 渲染位移
- css animate
- dom js 定时器设置左边距属性
content-box
和border-box
的区别?
border-box
:IE模型,不包含边框和内边距content-box
:默认值,W3C标准,包含边框和内边距
默认content-box
,可通过box-sizing
指定。
浏览器篇
了解解释器的GC机制否?
垃圾标记
- 执行标记:变量进入执行上下文和执行完上下文都分别有标记
- 引用计数:底层计算变量被引用了几次,为0则释放(Python目前也如此)
垃圾回收
- 周期回收:类似内存监听/拦截,比如隔多久事件回收一次,内存使用率超多少回收一次
- 阈值回收:早期 IE 的 GC 机制,比如变量超过多少个就执行回收
- 动态阈值回收:IE7 中对IE本身 GC 的优化,阈值根据内存占用率和规律来确定,效果很好
- 增量回收:Chrome中的机制,因为 GC 会产生不同时间的线程阻塞,所以不能一次处理太多,要分批次回收
- 优化回收:回收内存后,可能会出现内存碎片(不连贯),所以回收同时进行整理
Web缓存?
Cache-Control
:指定过期时间、缓存状态、选项,优先级高于 ExpiresExpires
: 1.0协议中的头,指定缓存过期时间Last-modified
:服务端资源最后变更时间,若资源未变更会返回304If-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 堆:存放被引用的引用类型数据
如果一个值是引用类型的,那么它的存储空间将从堆中分配。由于引用值的大小会改变,所以不能把它放在栈中,否则会降低变量查寻的速度。
相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,所以把它存储在栈中对变量性能无任何负面影响。
undefined 与 null 的区别?
基本同义,但不完全同义。
由于运算中的隐式转换会导致,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是啥?
当前执行上下文环境。
深拷贝方法?
- 序列化
- 递归
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
将子类构造函数的原型设置为父类构造函数的实例。
示例:
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
调用父类的属性方法;
本质上:依旧使用原型 + 原型链实现继承。
不同点:两条继承链:一条实现构造函数的继承,一条实现原型的继承。
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 中继承和重载都是模拟多态的表现形式。
元素节点、文本节点、属性节点还记得是啥东西?
都是 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。
Angular1.x.x中使用脏检查,脏检查:封装所有可封装的事件,每次发生任何事件,进行大检查,不超过10次,不低于2次。
也有纯粹使用观察者模式的,像:backbone.js。
React、Vue、Angular(>2.xx) 的不同?
定位:
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 - 开发模式:React严格上只针对MVC的view层,Vue则是MVVM模式的一种实现
- 数据更新:
- Vue 采用依赖追踪,默认就是优化状态:有多少数据变动,就会触发多少更新,不多也不少。
- React 可以手动添加 shouldComponentUpdate 来避免不需要的 re-render
- Vue 采用依赖追踪,默认就是优化状态:有多少数据变动,就会触发多少更新,不多也不少。
- 数据管理:React 和 Vue 的单向数据流管理机制也非常类似,React 有 Redux,Vue 有 Vuex,但 vue本身提供了双向数据绑定;Angular 则使用 RxJS 来实践数据管理,也可以转为 Promose 哈;Angular 使用强类型 TS 作为母语,有内置的强壮的模块来实现各种需求
共同点:
目前三者的社区热度都很火热,生态链也很完善,都是相对成熟的技术栈。越来越趋于同质化,在web components
真正成熟之前,各种框架都在探索一种类似的组件抽象机制;
同时都期望框架不单单是实现 Web 端的应用开发,Angular 可以和 nativescript 开发原生客户端应用,Vue 有 Weex 解决方案,Racct 更有火遍全世界的 React-Native 框架;
Angular 本身支持 SSR,React 有 Next.js,Vue 有 Nuxt.js。
本质:
框架本身只是工具,只是为了我们更快搭建应用诞生的,没有谁最好谁不好,选择适合的最好,为了追新而实践是一定一定要避免的。
工具篇
Grunt、Gulp、Webpack区别?
Grunt、Gulp应该可以称之为自动化工具,他可以自动化地帮我们处理对特定资源/事件的处理,其实在这两者出现之前,很多有条件的团队一直在实践一些基于 Python、Java、Php 的工具来完成这些事。
Webpack是一个基于node的资源处理工具,更像一个平台或中介者,我们可以基于它配置各种插件扩展用于处理不同的文件资源,并做出相应输出,可能是编译、分包、压缩、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
是啥?GET
和POST
的本质区别:
一句话:url 仅代表资源,HTTP 请求类型来描述操作动作。
本质上,GET
就是请求,且 URL 的长度有限制,一般在2k之内;
POST
就是发送数据,以body
为数据宿主,常见类型有:application/json
xml
text
formData
等;
PUT
用于全量修改,PATCH
用于单量修改,DELETE
按照标准是不支持 body 的,但大部分浏览器和服务端都兼容实现了,但在代理情况下,数据可能会丢失。
底层篇
算法复杂度的概念?
算法在编写成可执行程序后,运行时所需要的资源,资源包括时间资源和内存资源。
一般称之为:时间复杂度和空间复杂度。
如:
- 循环一次 = n
- 循环两次 = 2n(n)
- 嵌套两层循环 = n²
- …
Url 从输入到展现的过程?
浏览器 DNS 缓存 => 本机 DNS 缓存 => LDNS(NS) => RDNS(GTLD) => NS(IP) => IP
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 or UDP)之间增加一个二进制分帧层。
在二进制分帧层中, HTTP/2 会将所有传输的信息分割为更小的消息和帧(frame),并对它们采用二进制格式的编码 ,其中 HTTP1.x 的首部信息会被封装到 HEADER frame,而相应的 Request Body 则封装到 DATA frame 里面。
首部压缩(Header Compression)
使用 HPACK 算法将重复的、多余的、正常的头部信息进行压缩处理。
服务端推送(Server Push)
简单说:当一个客户端请求资源X,而服务器知道它很可能也需要资源Z的情况下,服务器可以在客户端发送请求前,主动将资源Z推送给客户端。
负载均衡?
负责均衡的具体就是让每一层在访问自己的上游层时做到计算单元分配最大均匀化。
负责均衡有多个层面:
- 客户层:client,由”DNS-server轮询”实现”clict => ip”的分配
- 反代层:nginx,由”upstream(默认轮询)”实现”请求 => Web server”的分配
- 站点层:Web server,由”服务连接池”实现对服务层访问的分配
- 服务层:Service,需平衡”数据均衡”与”请求均衡”两个点
- 数据层:Database/cache
相关:一分钟了解负载均衡的一切
如何保证程序的健壮性?
- 灰度发布:一次只向一部分用户发布功能,比较强大的如facebook,可以向特定年龄,文化,时间段的用户发布。比如弱的,也可以向特定的IP发布。
- 监控服务:Core Dump 监控、Log 监控、CPU 监控、内存监控…
- 容灾措施:xxx
思考篇
学习方法?
根据大致目录简历思维大导图,构建知识图谱,主要靠文档,然后实践。
对新技术的看法和了解渠道?
掘金、V站、开源中国,必须了解、及时学习、按需实践,绝不为了实践而实践,也不过于被动保守避免重构升级。
任意连续的三个正整数相乘,一定能被6整除吗,为什么?
因为三个连续的正整数中必有一个能被3整除,还有一个能被2整除.所以必能被6整除.
未完
原文地址:https://surmon.me/article/51 作者:surmon