1、event loop是什么?
主线程和任务队
2、HTTP协议与状态码,HTTP2.0等,状态码301、302等
3、原生实现promise
//原生js实现promise
function PromiseM() {
this.status = "pending"
this.mag = ""
let process = arguments[0]
let that = this
process(function(){
that.status = "resolve"
that.msg = arguments[0]
},function(){
that.status = "reject"
that.msg = arguments[0]
})
return this
}
PromiseM.prototype.then = function() {
let resolve = arguments[0]
let reject = arguments[1]
if(this.status == "resolve") {
resolve(this.msg)
}
if(this.status == "reject" && arguments[1]) {
reject(this.msg)
}
}
4、CSS3中display属性的Flex布局
http://www.cnblogs.com/xuyuntao/articles/6391728.html
5、浏览器缓存相关、强缓存与协商缓存、浏览器 http 200(from cache)和304的区别
https://segmentfault.com/a/1190000012897512
6、解决跨域的方法
jsonp、window.postMessage等
7、跨域资源共享 CORS
http://www.ruanyifeng.com/blog/2016/04/cors.html
8、typeof返回哪些数据类型
https://blog.csdn.net/yellowmushroom/article/details/80249493
9、Vue.nextTick()
10、css盒子模型
https://blog.csdn.net/zlingyun/article/details/81835665
11、原生实现bind函数
12、手写一个object的深克隆
13、算法-将以下数据结构按顺序输出
var arr = [
[1,2,3,4,5],
[16,17,18,19,6],
[15,24,25,20,7],
[14,23,22,21,8],
[13,12,11,10,9]
]
14、算法-根据数据生成一个树状结构的对象
var aTree = [
{"id": "1", "name": "动物", "pid": "0"},
{"id": "2", "name": "鸟类", "pid": "5"},
{"id": "3", "name": "无脊椎动物", "pid": "1"},
{"id": "4", "name": "哺乳动物", "pid": "5"},
{"id": "5", "name": "脊椎动物", "pid": "1"},
{"id": "6", "name": "喜鹊", "pid": "2"},
{"id": "7", "name": "蚯蚓", "pid": "3"}
];
15、函数节流与函数防抖
16、图片懒加载
图片懒加载实现(js部分):
var imgSrc = "https://ss1.bdstatic.com/5aAHeD3nKgcUp2HgoI7O1ygwehsv/media/ch1000/png/pct1.png"
var io = new IntersectionObserver(function(entries){
entries.forEach(function(value){
if(value.intersectionRatio > 0) {
var target = value.target
//var src = target.dataset.src
target.src = imgSrc;
io.unobserve(target)
console.log(111)
}
})
})
var imgs = Array.from(document.querySelectorAll("#isImg"))
console.log(imgs)
imgs.forEach(function(item){
io.observe(item)
WaitGroup主要是三个方法,Add(int),Done()和Wait(), 其中Done()是调用了Add(-1),推荐使用方法是,先统一Add,在goroutine里并发的Done,然后Wait
WaitGroup主要维护了2个计数器,一个是请求计数器 v,一个是等待计数器 w,二者组成一个64bit的值,请求计数器占高32bit,等待计数器占低32bit。
简单来说,当Add(n)执行时,请求计数器 v 就会加n,当Done()执行时,v 就会减1,可以想到,v 为0时就是结束,可以触发Wait()执行了,所谓的触发Wait()是通过信号量实现的。
那么等待计数器拿来干嘛?是因为Wait()方法支持并发,每一次Wait()方法执行,等待计数器 w 就会加1,而等待v为0触发Wait()时,要根据w的数量发送w份的信号量,正确的触发所有的Wait()。
同时,WaitGroup里还有对使用逻辑进行了严格的检查,比如Wait()一旦开始不能Add().
下面是带注释的代码:
复制代码
func (wg *WaitGroup) Add(delta int) {
statep := wg.state()
// 更新statep,statep将在wait和add中通过原子操作一起使用
state := atomic.AddUint64(statep, uint64(delta)<<32)
v := int32(state >> 32)
w := uint32(state)
if v < 0 {
panic("sync: negative WaitGroup counter")
}
if w != 0 && delta > 0 && v == int32(delta) {
// wait不等于0说明已经执行了Wait,此时不容许Add
panic("sync: WaitGroup misuse: Add called concurrently with Wait")
}
// 正常情况,Add会让v增加,Done会让v减少,如果没有全部Done掉,此处v总是会大于0的,直到v为0才往下走
// 而w代表是有多少个goruntine在等待done的信号,wait中通过compareAndSwap对这个w进行加1
if v > 0 || w == 0 {
return
}
// This goroutine has set counter to 0 when waiters > 0.
// Now there can‘t be concurrent mutations of state:
// - Adds must not happen concurrently with Wait,
// - Wait does not increment waiters if it sees counter == 0.
// Still do a cheap sanity check to detect WaitGroup misuse.
// 当v为0(Done掉了所有)或者w不为0(已经开始等待)才会到这里,但是在这个过程中又有一次Add,导致statep变化,panic
if *statep != state {
panic("sync: WaitGroup misuse: Add www.michenggw.com called concurrently with Wait")
}
// Reset waiters count to 0.
// 将statep清0,在Wait中通过这个值来保护信号量发出后还对这个Waitgroup进行操作
*statep = 0
// 将信号量发出,触发wait结束
for ; w != 0; w-- {
runtime_Semrelease(&wg.sema, false)
}
}
// Done decrements the WaitGroup counter by one.
func (wg *WaitGroup) Done() {
wg.Add(-1)
}
// Wait blocks until the WaitGroup counter is zero.
func (wg *WaitGroup) Wait() {
statep := wg.state()
for {
state := atomic.LoadUint64(statep)
v := int32(state www.dasheng178.com>> 32)
w := uint32(state)
if v == 0 {
// Counter is 0, no need to wait.
if race.Enabled {
race.Enable()
race.Acquire(unsafe.Pointer(wg))
}
return
}
// Increment waiters count.
// 如果statep和state相等,则增加等待计数,同时进入if等待信号量
// 此处做CAS,主要是防止多个goroutine里进行Wait()操作,每有一个goroutine进行了wait,等待计数就加1
// 如果这里不相等,说明statep,在 从读出来 到 CAS比较 的这个时间区间内,被别的goroutine改写了,那么不进入if,回去再读一次,这样写避免用锁,更高效些
if atomic.CompareAndSwapUint64(statep,www.mhylpt.com/ state, state+1) {
if race.Enabled && w == 0 {
// Wait must be synchronized with the first Add.
// Need to model this is as a write to race with the read in Add.
// As a consequence, can do the write only for the first waiter,
// otherwise concurrent Waits www.fengshen157.com/ will race with each other.
race.Write(unsafe.Pointer(&wg.sema))
}
// 等待信号量
runtime_Semacquire(&wg.sema)
// 信号量来了,代表所有Add都已经Done
if *statep != 0 {
// 走到这里,说明在所有Add都已经Done后,触发信号量后,又被执行了Add
panic("sync: WaitGroup is reused before previous Wait has returned")
}
17、怎么去掉首尾的空格(多种方法)
18、事件触发机制以及为什么将事件绑定在冒泡阶段?
19、vue-router的配置
20、为什么说virtual DOM渲染更快
21、HTTP的各种状态码
原文地址:https://www.cnblogs.com/qwangxiao/p/10348935.html