程序员这行若是想一直作下去,那么持续学习是必不可少的。html
你们找工做一般会喜欢技术氛围好点的团队,由于这样可以帮助本身更好的成长,可是并非每一个团队都拥有这样的氛围。因而萌发一个念头,想创建一个地方,让一些人能在这块地方记录本身学习到的内容。这些内容一般会是一个小点,可能并不足以写成一篇文章。可是这个知识点可能不少人也不知道,那么经过这种记录的方式让别人一样也学习到这个知识点就是一个很棒的事情了。node
若是你也想参与这个记录的事情,欢迎贡献你的一份力量,地址在这里。react
本周总共有 55 人贡献了他们所学到的知识,如下是一些整合后的内容,更详细的内容推荐前往仓库阅读。ios
window.addEventListener('resize', function () {
if (
document.activeElement.tagName === 'INPUT' ||
document.activeElement.tagName === 'TEXTAREA' ||
document.activeElement.getAttribute('contenteditable') == 'true'
) {
window.setTimeout(function () {
if ('scrollIntoView' in document.activeElement) {
document.activeElement.scrollIntoView();
} else {
// @ts-ignore
document.activeElement.scrollIntoViewIfNeeded();
}
}, 0);
}
})
复制代码
首先是实现图片懒加载git
<ul>
<li><img src="./img/default.png" data="./img/1.png" alt=""></li>
<li><img src="./img/default.png" data="./img/2.png" alt=""></li>
<li><img src="./img/default.png" data="./img/3.png" alt=""></li>
<li><img src="./img/default.png" data="./img/4.png" alt=""></li>
<li><img src="./img/default.png" data="./img/5.png" alt=""></li>
<li><img src="./img/default.png" data="./img/6.png" alt=""></li>
<li><img src="./img/default.png" data="./img/7.png" alt=""></li>
<li><img src="./img/default.png" data="./img/8.png" alt=""></li>
</ul>
let imgs = document.querySelectorAll('img')
// 窗口可视区高度
let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
// img 距离窗口可视区顶部的距离 imgs[i].getBoundingClientRect().top
function lazyLoadImg () {
for (let i = 0; i < imgs.length; i ++) { if((imgs[i].getBoundingClientRect().top + imgs[i].height)>=0&&imgs[i].getBoundingClientRect().top < clientHeight ){ imgs[i].src = imgs[i].getAttribute('data') } } } window.addEventListener('scroll', lazyLoadImg); 复制代码
可是这种方式会引发图片下载过程当中闪白一下,能够经过 JS 预先加载图片解决。程序员
同时上述的懒加载解决方案已经很老了,可使用最新的 API Intersection_Observer 来作这件事,会更简单并且可控一些。github
const List1 = len => ''.padEnd(len, ',').split('.')
const List2 = len => [...new Array(len).keys()]
复制代码
今天刷博客的时候看到一个题:npm
const pro = new Promise((resolve, reject) => {
const pro1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(3);
}, 0);
});
resolve(4);
pro1.then((args) => {
console.log(args);
});
});
pro.then((args) => {
console.log(args);
});
复制代码
不少人都知道这道题的输出结果是4,3;可是我对题主的这个问题产生了很大的疑问,由于我的并无着手实现过符合promise A/A+规划的promise,因此每次作这种题都是凭着平时的使用经验,实际上心里虚得很,而后本身查阅了 spec:ECMAScript 2018 Language Specification 根据 spec,若是调用 then 时 promise 是 pending 状态,回调会进入 promise 的 [[PromiseFulfill/RejectReactions]] 列表里;不然会进入 PromiseJobs。windows
PromiseJob 以及 Job Queue 是 ES 中的说法,而 macroTask 和 microTask 是浏览器中的概念,包括 setTimeout 也是宿主环境提供的。所以输出 4 3 是 ECMAScript 和 浏览器两种规范共同约束的结果。数组
PromiseJob 对应浏览器中的一个 microTask。对于调用 then 时 promise 处于 pending 状态,回调函数进入到对应的 reactions 队列中。当该 promise 被 fulfill 或 reject 时,则 flush 对应的 reactions 队列 ,其中的每一个 reaction 对应一个 PromiseJob 被按序 enqueue 到 Job Queue若是调用 then 时 promise 处于其余两个状态,JS 引擎就直接 enqueue 一个对应的 PromiseJob 到 Job Queue示例中的代码。
在浏览器中以下顺序:
0. current cycle of evevt loop start
1. Install Timer,Timer get enqueued
2. Resovle pro, because there is no fulfillReaction binding to pro, do nothing
3. call then() at pro1, because pro1 is pending, add fulfillReaction to pro1
4. call then() at pro, because pro is reolved,immediately enqueue a PromiseJob
5. current macroTask is finished
6. run all PromiseJobs(microTasks) in order,
7. console.log(4)
8. current cycle of event loop is finishedanother cycle starts
9. Timer Fires, and pro1 is resolved
10. at this time, pro1 hasfulfillReactions,enqueue every fulfillReaction as a PromiseJob in order
11. current macro Job is finished
12. run all PromiseJobs in order
13. console.log(3)
14. current cycle of event loop is finished
复制代码
navToDownApp() {
let u = navigator.userAgent
if (/MicroMessenger/gi.test(u)) {
// 若是是微信客户端打开,引导用户在浏览器中打开
alert('请在浏览器中打开')
}
if (u.indexOf('Android') > -1 || u.indexOf('Linux') > -1) {
// Android
if (this.openApp('en://startapp')) {
this.openApp('en://startapp') // 经过Scheme协议打开指定APP
} else {
//跳转Android下载地址
}
} else if (u.indexOf('iPhone') > -1) {
if (this.openApp('ios--scheme')) {
this.openApp('ios--scheme') // 经过Scheme协议打开指定APP
} else {
// 跳转IOS下载地址
}
}
},
openApp(src) {
// 经过iframe的方式试图打开APP,若是能正常打开,会直接切换到APP,并自动阻止a标签的默认行为
// 不然打开a标签的href连接
let ifr = document.createElement('iframe')
ifr.src = src
ifr.style.display = 'none'
document.body.appendChild(ifr)
window.setTimeout(function() {
// 打开App后移出这个iframe
document.body.removeChild(ifr)
}, 2000)
}
复制代码
function parseURL(url) {
var a = document.createElement('a');
a.href = url;
return {
host: a.hostname,
port: a.port,
query: a.search,
params: (function(){
var ret = {},
seg = a.search.replace(/^\?/,'').split('&'),
len = seg.length, i = 0, s;
for (;i<len;i++) {
if (!seg[i]) { continue; }
s = seg[i].split('=');
ret[s[0]] = s[1];
}
return ret;
})(),
hash: a.hash.replace('#','')
};
}
复制代码
var array = [1, 2, 1, 1, '1'];
function unique(array) {
var obj = {};
return array.filter(function(item, index, array){
return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
})
}
复制代码
利用一个空的 Object 对象,咱们把数组的值存成 Object 的 key 值,好比 Object[value1] = true,在判断另外一个值的时候,若是 Object[value2]存在的话,就说明该值是重复的。
由于 1 和 '1' 是不一样的,可是这种方法会判断为同一个值,这是由于对象的键值只能是字符串,因此咱们可使用 typeof item + item 拼成字符串做为 key 值来避免这个问题
上周在实现某个弹层功能的时候,用到了rc-util
里的 contains
方法函数, 结果 code-review
的时候同事对该代码提出了疑问:
export default function contains(root, n) {
let node = n;
while (node) {
if (node === root) {
return true;
}
node = node.parentNode;
}
return false;
}
复制代码
上述代码是 antd
内部抽象的一个工具方法,用来判断某个dom是否为另外一个dom的祖先节点。
同事疑问的是 let node = n;
这段代码是否是多余的?
首先一开始的理解是 函数参数 n
是一个对象,一个dom
节点对象。
若是用 node
保存 n
的值,防止 node = node.parentNode
这段代码执行的时候,会改变传入的实参 n
对应的值。
毕竟如下的代码咱们都很熟悉:
function contains(root, n) {
if(n) {
n.a = 3
}
}
const A = {a:1};
const B = {a:2};
contains(A,B)
console.log(B) // {a:3}
复制代码
即当实参为对象时,函数内部是能够改变该对象的值从而影响函数以外的实参。
可是测试另一段代码,发现和理解的不同:
function contains(root, n) {
if(n) {
n = {a:3}
}
}
const A = {a:1};
const B = {a:2}
contains(A,B)
console.log(B) // {a:2}
复制代码
即 n.a = 3
和 n = {a:3}
这两段代码是不同的。
网上也有相关资料,其实能够简单的理解为: 当函数一开始执行时,n
是指向实参 B
的一个引用.
n.a = 3
是在引用上再关联了一个属性,此时和 B
仍是同一个引用,所以会改变实参B
的值。
而 n = {a:3}
则使得 n
再也不指向实参 B
, 而是指向一个新对象{a:3}
,也就是 n
与 B
完全断绝了关系,所以不会改变实参 B
的值。
是否是能够给蚂蚁的团队提个issue建议删除该代码,不过有这句代码也不会有什么bug~
相关资料:JavaScript深刻之参数按值传递
如下命令能够 kill 掉 8080 端口,固然你也能够选择经过 npm 命令的方式指定须要 kill 的端口。
lsof -i tcp:8080 | grep LISTEN | awk '{print $2}'| awk -F"/" '{ print $1 }' | xargs kill -9
复制代码
另外以上命令在 windows 上是不可用的。若是有多平台的需求的话,能够直接使用 Kill-port-process。
# 将wxml文件的i标签替换为text
grep '<i ' -rl . --include='*.wxml' --exclude-dir=node_module --exclude-dir=dist | xargs sed -i -e 's/<i /<text /g'
grep '</i>' -rl . --include='*.wxml' --exclude-dir=node_module --exclude-dir=dist | xargs sed -i -e 's/<\/i>/<\/text>/g'
复制代码
文章连接,经过这篇文章能够了解到换行符究竟是什么。
另外这位大佬天天都将学习到的知识记录了下来,感兴趣的能够 阅读一下。
这周的分享内容质量很高,我也从中汲取到了一些知识。
这是一个须要你们一块儿分享才能持续下去的事情,光靠我一人分享是作不下去的。欢迎你们参与到这件事情中来,地址在这里。