html, 浏览器
DOM是什么?有什么API
DOM是页面的一个个节点,可以对其进行修改进而改变页面内容
在浏览器渲染机制中,浏览器解析HTML标签,构建DOM树
- API:
- getElementByTagName
- getElementById
如何提高前端性能
- 尽量减少 HTTP 请求个数——须权衡
- 使用 CDN(内容分发网络)
- 为文件头指定 Expires 或 Cache-Control ,使内容具有缓存性。
- 避免空的 src 和 href
- 使用 gzip 压缩内容
- 把 CSS 放到顶部
把 JS 放到底部 - 避免使用 CSS 表达式
- 将 CSS 和 JS 放到外部文件中
- 减少 DNS 查找次数
- 精简 CSS 和 JS
- 避免跳转
- 剔除重复的 JS 和 CSS
- 配置 ETags
- 使 AJAX 可缓存
- 尽早刷新输出缓冲
- 使用 GET 来完成 AJAX 请求
- 延迟加载
- 预加载
- 减少 DOM 元素个数
- 根据域名划分页面内容
- 尽量减少 iframe 的个数
- 避免 404
- 减少 Cookie 的大小
- 使用无 cookie 的域
- 减少 DOM 访问
- 开发智能事件处理程序
- 用 代替 @import
- 避免使用滤镜
- 优化图像
- 优化 CSS Sprite
- 不要在 HTML 中缩放图像——须权衡
- favicon.ico要小而且可缓存
- 保持单个内容小于25K
- 打包组件成复合文本
cookie 与 session
https://juejin.im/entry/59deb90f518825569538a359
- 用户首次访问服务器,服务器在header附上set-cookie。浏览器将cookie保存在本地。之后用户访问服务器都会带上这段cookie
- cookie有失效时间,可以通过expire或max_age修改
- cookie 会收到XSS(跨站脚本攻击),通过设置属性http-only可以屏蔽来自<script>的访问
- session存储在服务器,服务器为每个会话创建一个sessionId。sessionId由浏览器保存(可以用cookie保存)
- cookie不超过4K,session能到5M
CSS
css盒模型
内容(content),边框(border),内外边距(padding,margin)
如何让元素上下左右居中
为什么overflow:hidden能包含浮动元素?
浮动
元素设置为浮动后则脱离文档流,不属于当前父元素的子元素
此时通过设置overflow:hidden能够使父元素变为一个新的BFC(默认只有body这个BFC)
BFC有以下属性:
所以能够把浮动元素也包进去
通过划分BFC还能用来清除margin 合并
响应式和自适应布局
响应式和自适应的区别 (推荐)
解决方案:
- bootstrap
- 网页宽度自动调整
<meta name="viewport" content="width=device-width, initial-scale=1" />
- 百分比布局(width,height,font使用em / rem)
- 流动布局
- css3: media query. 根据分辩率加载指定css文件
- @media. 根据分辨率设置不同属性
书籍
tap为什么有300毫秒的延迟
移动端用户浏览的双击缩放行为,导致页面在接收到tap事件时,等待300ms确定是否有又一次tap。有则缩放,没有则点击
解决方式:
- 禁用缩放(修改meta)
- touch action:none
- fastclick:根据meta和touch-action响应式确定是否禁用缩放
css3动画和jquery动画的差别是什么
Css3 基于css实现机制的,效率高,兼容性差,采用gpu
jquery效率低于css3,兼容性好
em 和 rem 的区别
px
在缩放页面时无法调整那些使用它作为单位的字体、按钮等的大小em
的值并不是固定的,会继承父级元素的字体大小,代表倍数;rem
的值并不是固定的,始终是基于根元素<html>
的,也代表倍数。
css三栏布局,两侧固定,中间自适应
-
float实现
- 两边固定宽度,中间自适应
- 利用中间元素的margin来控制两边的边距
- 宽度小于左右部分宽度之和时,右侧部分会被挤下去
-
position实现
绝对定位
-
圣杯布局或双飞翼布局
<div class="wrap"> <div class="middle"> <div class="main">中间</div> </div> <div class="left">左侧</div> <div class="right">右侧</div> </div> <style type="text/css"> .wrap {overflow: hidden;} .left {float: left; width: 200px; height: 100px; background: coral; margin-left: -100%} .middle {float: left; width: 100%; height: 100px; background: lightblue;} .right {float: left; width: 120px; height: 100px; background: gray; margin-left: -120px;} .main {margin: 0 140px 0 220px; background: lightpink;} </style>
原因:元素在html中按 middle,left,right排列,假如不设置margin,则显示为
显然,middle撑开占据全部屏幕宽度,left,right被挤到下一行
所以margin-left: -100%
即元素想左移动屏幕宽度的长度,因此移到第一行并覆盖部分middle
接着将right移动它的自身宽度的负margin,刚好到达第一行末尾
-
flex 布局(最好)
- flex-direction
- Flex-wrep
- Flex-flow
- Justify-content
- Align-items
- Align-content
水平垂直居中,不知道尺寸(不能用absolute)
使用translate移动
difference between link and @import
- Link 在页面载入时同时加载,import在页面完全载入后加载,较慢
- link和import混用可能导致串行导入css,使得效率降低。
- link除了加载css外,还能加载RSS等
块级元素和行内元素
块级元素横向充满父元素,可以设置宽高;行内元素在同一行,不能设置宽高,但能设置margin-left/ right
块级元素:h,div, p, table
行内元素:img,a,input
为什么img可以设置宽高:
img,input属于替换元素,即浏览器可以根据实际内容进行显示,因此可以设置宽高
block,inline,inline-block
- inline
- respect left & right margins and padding, but not top & bottom
- cannot have a width and height set
- allow other elements to sit to their left and right.
- see very important side notes on this here.
- block
- respect all of those
- force a line break after the block element
- acquires full-width if width not defined
- Inline-block
- allow other elements to sit to their left and right
- respect top & bottom margins and padding
- respect height and width
为什么css放在头部,js放在尾部
-
CSS不会阻塞 DOM的解析,但会阻塞 DOM 渲染。
-
JS 阻塞DOM 解析,但浏览器会"偷看"DOM,预先下载相关资源。
-
浏览器遇到
<script>
且没有defer
或async
属性的 标签时,会触发页面渲染,因而如果前面CSS
资源尚未加载完毕时,浏览器会等待它加载完毕在执行脚本。
用css画三角形
#tri {
width: 0px;
height: 0px;
border-top: 50px solid yellow;
border-right: 50px solid red;
border-bottom: 50px solid yellow;
border-left: 50px solid green
}
将某三个border设为transparent
,则可获得一个三角形
从中也可以看出盒模型中不同的border边是如何划分的
能够得到三角形的关键原因在于width: 0px; height: 0px
,假如不设为0,则为
由此我们可以看出,这个三角形是通过具有一定厚度的border生成的。
并且也可以看出,设置width和height时,设置的是content
的尺寸
margin设置的四种方式
- 单值:所有边缘
- 二值:纵向横向
- 三值:上 横向 下
- 四值:上 右 下 左
css实现div无限旋转
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="try_2.css">
<title>Document</title>
</head>
<body>
<div id="rotate"></div>
</body>
</html>
/*----------- animation ----------*/
/* #rotate {
height: 100px;
width: 100px;
border: 1px solid red;
transform: transform
} */
/* #rotate {
height: 100px;
width: 100px;
border: 1px solid red;
animation: changebox 1s ease-in-out 1s infinite normal running both;
}
#rotate:hover {
animation-play-state: paused;
}
@keyframes changebox {
10% {
transform:rotate(75deg);
}
30% {
transform:rotate(150deg);
}
50% {
transform:rotate(225deg);
}
70% {
transform:rotate(300deg);
}
100% {
transform:rotate(360deg);
}
} */
/* -----------transform ---------*/
#rotate {
height: 100px;
width: 100px;
border: 1px solid red;
transition: transform 1s ease-in-out 0s;
}
#rotate:hover {
transform: rotate(360deg);
}
inline-height
行间距,基线
JS
跨域问题的解决方式
-
CORS头
-
jsonp
缺点:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题
- document.domain
原生 js 怎么发起 ajax 请求?
一个 XMLHttpRequest 实例有多少种状态?
websocket 和 长连接
websocket
http://www.ruanyifeng.com/blog/2017/05/websocket.html
- 一种新的协议,实现服务器和客户端的双向通信
- 客户端有一般的事件监听函数
- 服务端可使用socket.io
长连接
- 类似于长轮询,只不过hold的时间更长
用 js 怎样实现一个类?
js 没有类,只能申明 构造函数
js的继承问题
- js没有类,直接通过构造函数生成对象
- 构造函数 即 函数体中 包含 this 的函数
- 每个构造函数都有一个prototype属性,它的值是一个prototype对象,prototype对象中的所有属性在构造函数创建新对象时会自动继承
在寻找方法时,现在本对象查找,若找不到则去原型链查找 - 通过新建一个A对象赋给一个B对象的prototype,则相当于将A的所有方法挂到B上,就相当于继承
原型链
构造对象并生成原型链的方法
- 直接创建
- 构造器(构造函数)
- Object.create(原型)
- class
解释:
- 所有的构造函数
function
都有prototype
属性,指向一个它在创建对象时需要继承过来的对象 - 所有的对象(包括function)都有
_proto_
属性,指向它的父亲 - 构造函数
function
相当于母亲,因为她直接生出新对象,母亲调用prototype
则可指向父亲 _proto_
相当于父亲,因为孩子继承了_proto_
指向的对象的属性(基因),孩子调用_proto_
指向父亲- 所有
function
(包括Function
)的父亲(_proto_
)都是Function.prototype
(function Function
的老公兼父亲,wtf??) null
是所有对象的最高级祖先,第二级祖先则为Object.prototype
object.create 实质
Object.create = function (obj) {
function F() {}
F.prototype = obj;
return new F();
};
或
Object.create = function (obj) {
var B={};
B.__proto__=obj;
return B;
};
Object.create创建了一个新的对象,这个对象继承(关联)了obj的属性,改变新对象的同名属性并不会影响原对象。
如果直接用“=”来赋值,只是一个对象的引用。
假如在新对象里定义一个与原型链上的同名属性,会发生属性遮蔽,在本对象新建一个属性,该属性比原型上的属性有更高的优先级
//example 1:
var obj ={a: 1}
var b = obj
console.log(obj.a) // 1
console.log(b.a) // 1
b.a = 2
console.log(obj.a) //2
//example 2:
var obj ={a: 1}
var b = Object.create(obj)
console.log(obj.a) // 1
console.log(b.a) // 1
b.a = 2
console.log(obj.a) //1
new的实质
若执行 new Foo(),过程如下:
1)创建新对象 o;
2)给新对象的内部属性赋值,关键是给[[Prototype]]属性赋值,构造原型链(如果构造函数的原型是 Object 类型,则指向构造函数的原型;不然指向 Object 对象的原型);
3)执行函数 Foo,执行过程中内部 this 指向新创建的对象 o;
4)如果 Foo 内部显式返回对象类型数据,则,返回该数据,执行结束;不然返回新创建的对象 o。
例子:
function Foo(age) {
this.age = age;
}
var o = new Foo(111);
console.log(o);
// 打印出来的是 {age: 111}。
function Foo(age) {
this.age = age;
return { type: "我是显式返回的" };
}
var o = new Foo(222);
console.log(o);
// 打印出来的是 {type: '我是显式返回的'},也就是说,return 之前的工作都白做了,最后返回 return 后面的对象。
function Foo(age) {
this.age = age;
return 1;
}
var o = new Foo(333);
console.log(o);
// 打印出来的是 {age: 333},和没有 return 时效果一样。
实现:
function _new () {
// arguments实际上是一个类数组对象,需要转成数组
let args = [].slice.call(arguments)
// 第一个参数是构造函数,把它拿出来
let constructor = args.shift()
// Object.create()返回一个新对象,这个对象的构造函数的原型指向Foo
let context = Object.create(constructor.prototype)
// 在返回的context对象环境中执行构造函数,为新的context添加属性
let result = constructor.apply(context, args)
// 如果Foo显示的返回了一个对象,那么应该直接返回这个对象,而不用理会以上所有的操作,一般不会发生这种情况,但是new的实现的确是这样的逻辑
// 这里之所以判断类型是否为object还要添加 != null 的判断,是因为null的typeof结果也是‘object’
// 不同的对象在底层都表示为二进制,在Javascript中二进制前三位都为0的话会被判断为Object类型,null的二进制表示全为0,自然前三位也是0,所以执行typeof时会返回"object"
return (typeof result === 'object' && result != null) ? result : context
}
function Foo (name) {
this.name = name
}
Foo.prototype.getName = function() {
console.log(this.name)
}
var a = _new(Foo, 'tom')
a.getName()
js 中怎么实现封装和多态?
通过继承就能实现多态呗
js闭包问题
js 的字符串类型有哪些方法?
chartat 获取指定位置字符,相当于下标
indexof 查找字符的位置
concat 字符串连接
slice = substring = substr (开始位置,结束位置)。返回子字符串
split()按字符分割
trim()生成副本,删除开始和结束空格
replace(原字符串,替换字符串),替换第一个匹配
replace (/正则/g,替换字符串)。替换所有
jquery 的常见方法
阮一峰
选择,链式操作,end回退
取值,赋值
如何跨标签页通信?比如一个页面和它里面的 iframe 通信。
postMessage(信息,协议+主机+端口号)
接收方添加message监听事件
ajax无法回退的方案
个人理解
由于ajax请求发出时不会改变页面url,所以通过window.history.pushstate
改变url,但不会进行跳转,则这次操作被记录下来,之后采取popstate即可。
抽象语法树 AST (不太清楚)
模版引擎
- 传入 模版 和 数据 ,转化为 html,如handlebar
- jade属于服务端
js如何深度克隆一个对象
-
简单来讲就是判断类型
-
递归复制属性
-
非引用类型直接返回
const deepClone = function(obj) {
// 先检测是不是数组和Object
// let isArr = Object.prototype.toString.call(obj) === '[object Array]';
let isArr = Array.isArray(obj);
let isJson = Object.prototype.toString.call(obj) === '[object Object]';
if (isArr) {
// 克隆数组
let newObj = [];
for (let i = 0; i < obj.length; i++) {
newObj[i] = deepClone(obj[i]);
}
return newObj;
} else if (isJson) {
// 克隆Object
let newObj = {};
for (let i in obj) {
newObj[i] = deepClone(obj[i]);
}
return newObj;
}
// 不是引用类型直接返回
return obj;
};
Object.prototype.deepClone = function() {
return deepClone(this);
};
Object.defineProperty(Object.prototype, 'deepClone', {enumerable: false});
登录验证怎么做的
https://segmentfault.com/a/1190000013010835
- token可以避免CSRF(跨站请求伪造攻击)
- 客户端向服务端发送用户名和密码后,服务端返回一段token。之后的业务请求都带上这段token
- token可以通过服务端签名认证实现无状态。服务端只要知道这是自己的签名就好
- 无状态token使得认证与业务分离成为可能
强缓存和协商缓存
https://www.jianshu.com/p/1a1536ab01f1
- 浏览器第一次加载资源,服务器返回200,浏览器将资源文件从服务器上请求下载下来,并把response header及该请求的返回时间一并缓存;
- 下一次加载资源时,先比较当前时间和上一次返回200时的时间差,如果没有超过cache-control设置的max-age,则没有过期,命中强缓存,不发请求直接从本地缓存读取该文件(如果浏览器不支持HTTP1.1,则用expires判断是否过期);如果时间过期,则向服务器发送header带有If-None-Match和If-Modified-Since的请求
- 服务器收到请求后,优先根据Etag的值判断被请求的文件有没有做修改,Etag值一致则没有修改,命中协商缓存,返回304;如果不一致则有改动,直接返回新的资源文件带上新的Etag值并返回200;
- 如果服务器收到的请求没有Etag值,则将If-Modified-Since和被请求文件的最后修改时间做比对,一致则命中协商缓存,返回304;不一致则返回新的last-modified和文件并返回200;
强缓存:浏览器不会像服务器发送任何请求,直接从本地缓存中读取文件并返回Status Code: 200 OK
协商缓存: 向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存,如果命中,则返回304状态码并带上新的response header通知浏览器从缓存中读取资源;
ES6
promise
- 封装一个异步操作,有pending,fulfilled,rejected三种状态
- resolve(sth)表示一步操作成功,并将参数传给then
- reject(sth)表示失败,将参数传给 then
- promise一定义马上执行,then中的代码则等到所有同步代码执行完成后才会执行
可暂停的函数 generator
- 定义一个generator函数:function * func () {}
- 调用 func(),返回一个遍历器对象,指向generator中的所有状态
- 每次调用next,则从上个yield执行到下个yield或return,返回 value 和 done。 value是yield后语句的执行结果,done标示是否完成,当最后一个yield结束后即done
var 与 let
var(es5): 分为全局变量或局部变量。以 function 来区分
let : 块级作用域,以大括号来区分
另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
const 不可变
如何及时捕获前端出现的异常
使用window.onError
使用ACCESS-control-alow-origin : * 解决跨域
使用AST
js 基本数据类型
基本数据类型:Undefined,Null,Boolean,Number,String,Symbol
存放在栈中
引用数据类型:Object
变量标识符以及指向对象的指针存放在栈中
对象的内容存放在堆中
js 垃圾回收机制
引用计数:根据引用,当对象零引用时回收。会出现循环引用的问题
标记清除法:设定一个root对象,从根开始查找所有不能获得的对象
bind
定义函数,绑定参数,返回值为函数。这个函数可以继续传参,不过改变了this
作为构造函数时,this则要被忽略了
call和apply的区别
- apply:
- 第一个参数改变this指向
- 第二个参数是数组
- call :
- 第一个参数改变this指向
- 第二个参数一个一个传入
this 和 that
this 是每个函数都会定义的对象,全局状态下,为window
因此在click时间中,假如新建一个函数或者什么,为了保留被点击的对象,则使用that = this
eventloop
lazy load 的三种实现方式
- 将scroll事件绑定一个监听函数。函数遍历每张图片,当图片出现在可见范围时,渲染。
- 函数节流(throttle)和去抖(debounce)
- intersectionObserverAPI
浏览器渲染原理
浏览器渲染页面的过程
- DNS 查询
- TCP 连接
- HTTP 请求即响应
- 服务器响应
- 客户端渲染
客户端渲染的步骤
- 处理 HTML 标记并构建 DOM 树。
- 处理 CSS 标记并构建 CSSOM 树。
- 将 DOM 与 CSSOM 合并成一个渲染树。
- 根据渲染树来布局,以计算每个节点的几何信息。
- 将各个节点绘制到屏幕上。
CSS 与 JS 是这样阻塞 DOM 解析和渲染的
CSS
不会阻塞 DOM
的解析,但会阻塞 DOM
渲染。
JS
阻塞 DOM
解析,但浏览器会"偷看"DOM
,预先下载相关资源。
浏览器遇到 <script>
且没有defer
或async
属性的 标签时,会触发页面渲染,因而如果前面CSS
资源尚未加载完毕时,浏览器会等待它加载完毕在执行脚本。
所以,你现在明白为何<script>
最好放底部,<link>
最好放头部,如果头部同时有<script>
与<link>
的情况下,最好将<script>
放在<link>
上面了吗?
comment:
CSSOM树和DOM树是分开构建,之所以把link标签放抬头而script放body尾部,是因为浏览器遇到script标签时,会去下载并执行js脚本,从而导致浏览器暂停构建DOM。然而JS脚本需要查询CSS信息,所以JS脚本还必须等待CSSOM树构建完才可以执行。
这将相当于CSS阻塞了JS脚本,JS脚本阻塞了DOM树构建。是这样子的关联才对。
只要设置CSS脚本提前加载避免阻塞JS脚本执行时CSSOM树还没构建好,同时给script标签设置async就可以解决这个问题
proxy
ryf
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写
语法:
var obj = new Proxy(target, handler)
常用handler有:
get(target, prop, [receiver])
set(target, prop, value, [receiver])
计算机基础
三次握手问题
https://www.zhihu.com/question/24853633
- 三次握手我的是双方的数据原点
- 假如最后一次握手没有到达,此时客户端单方面认为establish,服务端认为active,服务端没有收到确认,则会超时重传。假如客户端此时发数据过来,那么服务端也自动改为establish
四次挥手,最后一个ACK丢了会怎么样?
-
server会再次发一个FIN
-
等待中的client会再次发送ACK(client等待2MSL(Maximum Segment Lifetime)的原因)
OSI七层模型
HTTP状态码
下面是常见的HTTP状态码:
- 200 - 请求成功
- 301 - 资源(网页等)被永久转移到其它URL
- 302 - 资源临时移动
- 304 - 未修改
- 404 - 请求的资源(网页等)不存在
- 500 - 内部服务器错误
正则表达式
排序的稳定性和不稳定性
排序算法的稳定性大家应该都知道,通俗地讲就是能保证排序前2个相等的数其在序列的前后位置顺序和排序后它们两个的前后位置顺序相同。再简单形式化一下,如果Ai = Aj,Ai原来在位置前,排序后Ai还是要在Aj位置前。
选择排序、快速排序、希尔排序、堆排序不是稳定的排序算法,而冒泡排序、插入排序、归并排序和基数排序是稳定的排序算法
观察者模式和发布-订阅模式
- 在观察者模式中,观察者是知道Subject的,Subject一直保持对观察者进行记录。然而,在发布订阅模式中,发布者和订阅者不知道对方的存在。它们只有通过消息代理进行通信。
- 在发布订阅模式中,组件是松散耦合的,正好和观察者模式相反。
- 观察者模式大多数时候是同步的,比如当事件触发,Subject就会去调用观察者的方法。而发布-订阅模式大多数时候是异步的(使用消息队列)
- 观察者 模式需要在单个应用程序地址空间中实现,而发布-订阅更像交叉应用模式
Vue
路由组件缓存
https://juejin.im/post/5b407c2a6fb9a04fa91bcf0d
- 在keep-alive中设置include和exclude
- 条件缓存:
1. vuex保存keepalive数组
2. 在beforeeach 和 beforerouteLeave 检验to,来确定是否将route放入该数组,并决定是否keep-alive
Vue: data 和 computed的区别
- data 负责的是数据与页面的绑定,指的是model与view之间的绑定。data中的对象会被转为getter和setter用来监听视图变化
- computed属于扩展数据,是从数据得来的数据。源数据改变时,他也会随之改变。源数据一般是data中的数据或vuex中的state
Vue 与 Jquery 的区别
- Jquery 操作DOM节点,对DOM节点进行操作,视图与数据和逻辑耦合。因此代码逻辑复杂时,需要操作大量DOM节点
- VUE通过MVVM实现视图层和数据和逻辑的分离
Vue双向绑定的原理
Proxy 和 Object.defineProperty的区别
vue3.0 开始使用proxy替换defineProperty
- Proxy可以直接监听对象而非属性,Object.defineProperty侦听属性
- Object.defineProperty无法侦测数组变换
原因:操作数组的方法,也就是 Array.prototype上挂载的方法并不能触发该属性的 setter
Vue 中解决这个问题的方法,是将数组的常用方法进行重写,通过包装之后的数组方法就能够去在调用的时候被监听到。
node.js
node.js的异步机制
-
所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
-
主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
-
一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。(每次从任务队列读取一个事件,算作一个event loop)
-
主线程不断重复上面的第三步。
-
定时器事件也会被放到任务队列中
-
两种API
process.nextTick
方法可以在当前"执行栈"的尾部----下一次Event Loop(主线程读取"任务队列")之前----触发回调函数setImmediate
方法则是在当前"任务队列"的尾部添加事件,也就是说,它指定的任务总是在下一次Event Loop时执行,这与setTimeout(fn, 0)很像
异步编程的四种方法
- 回调函数
- 发布-订阅模式(
jQuery.subscribe()
) - 事件监听
- promise
宏任务与微任务
https://juejin.im/post/5b73d7a6518825610072b42b
- promise then, catch, final 都属于微任务
- 微任务在宏任务前进行
- 只有回调属于异步,进入任务队列
算法
求二进制数中1的个数
-
普通法:移位 + & +计数
int BitCount(unsigned int n) { unsigned int c =0 ; // 计数器 while (n >0) { if((n &1) ==1) // 当前位是1 ++c ; // 计数器加1 n >>=1 ; // 移位 } return c ; }
-
快速法:循环清除1
int BitCount1(unsigned int n) { unsigned int c =0 ; // 计数器 for (c =0; n; n >>=1) // 循环移位 c += n &1 ; // 如果当前位是1,则计数器加1 return c ; }
有9个球和一个天平,有一球稍轻,用这天平最少几次可以找出(8个球也一样)
- 两边放3个
- 若平衡:从剩下的3个中取两个,两边各放一个
- 若不平衡:从较轻的3个中取两个,两边各放一个
海量数据题
- hash取模分为小文件
- 在小文件中排序(hash)
- 堆排序