前言:感觉任何行业开始都离不开一个借鉴,随着时间的积累,变得熟能生巧。能分辨出利于自己的,或是好用的。这篇文章算是一个积累或者在这个行业本人的部分映射/走向,随缘更新,大部分都是自己常用,但可能掉坑的,督促自己背下来。
零.趋势,前端顶峰,安全
2019的主体:
TypeScript
RN
一. CSS
1. x:nth-of-type(n) 获取父元素下,的第 n 个 x 元素,tips:n 从 0 开始。(注意我的断句!)
2.x:nth-child(n) x的父元素下,第 n 个元素,假如刚好是 x,则有效,tips:n 从 1 开始。
3.x:last-child x的父元素下,最后一个子元素,恰好为 x
1. overflow-y:auto 对于 overflow-y:scroll ,同样是对容器上下内容的裁剪,auto 比 scroll 更智能,超出显示滚动条,否则隐藏
1.transition 过渡
2.transform 变换
3.animation 动画
tips:参考 https://segmentfault.com/a/1190000004460780
二:Promise
1.Promise.all 的使用注意
Promise.all(arr).then(res => {
// 注意这里 item => 不加括号等于 {return JSON.parse(item.data).result )} 切记箭头函数与Promise的组合使用,一定要有return
return res.map(item => JSON.parse(item.data).result )
}).then(data => {
console.log(data)
})
三:ES6整理
1.函数默认参数 function fn (num = 200) { console.log(num) }; fn() 或 fn(300);
2.async await 可避免回调地狱。async function 大于 Promise,当然在多个 await 之间没有关联时, async await 假若出错将会中断执行,所以建议加上 try { 多条await语句位置 } catch (e) {};高端:let [a, b, c] = await Promise.all([fn1(), fn2(), fn3()])
3.过滤数组中重复的成员:[...new Set(array)] 或者 Array.from(new Set(array))
四:this
const obj = {
a: function() { console.log(this) },
b: {
c: function() {console.log(this)}
}
}
obj.a() // 打出的是obj对象, 相当于obj.a.call(obj)
obj.b.c() //打出的是obj.b对象, 相当于obj.b.c.call(obj.b)
1. 概念:this是函数用call方法调用时传递的第一个参数,而且它还可以手动更改,只有在调用的时候才能确定this的值。
/* 简单总结一下:函数完整的调用方法是使用call方法,包括test.call(context, name)和obj.greet.call(context,name),这里的context就是函数调用时的上下文,也就是this,只不过这个this是可以通过call方法来修改的;构造函数稍微特殊一点,它的this直接指向new之后返回的对象;window.setTimeout()和window.setInterval()默认的是this是window对象。 */
2.箭头函数默认绑定(继承)外层 this,并且无法使用call修改,引用MDN:箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this。
3.修改this默认为window的setTimeout
const obj = {
a: function() {
console.log(this)
window.setTimeout(() => {
console.log(this)
}, 1000)
}
}
obj.a.call(obj) //第一个this是obj对象,第二个this还是obj对象
五:关于 JQuery 完成使命,即将退出舞台
1.querySelector,querySelectorAll 快速获取DOM节点
2.classList 代替 addClass,removeClass
3.Animate.css
4.原生Fetch API(IE无法使用,需要配合Polyfill)及 axios 代替jq封装的ajax
六、超出隐藏
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;/*最后添加省略号*/
去浮动
.clearfix:after {
content: "";
display: block;
height: 0;
clear: both;
visibility: hidden;
overflow: hidden;
}
七、居中
.el { display: flex; align-items: center; justify-content: center; }
八:const 变量的内部状态是可修改的
九:文字不可选
.noselect { -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; }
十:回调函数带参将失去 this 指向
// 若参数 cb 改为 cb(),则失去 this 指向
fn(param, cb) {
cb()
}
cb () {
console.log(this)
}
十一:push 返回的是长度,所以请严格按照顺序书写,另外参照第【十八】的不可变性,我们可以使用 concat 代替 push 创建数组的副本
let arr = [3]
arr.push(4) // 2
console.log(arr) // [3, 2]
十二:find 与 filter 的区别,两个方法的原数组都不变,find 查出的是第一个符合的对象,不是数组。
十三:box-sizing: border-box 只需设置 width 与 height,line-height,不需要设置padding。
十四:export 导出
1.export default { xxx } // 一个 js 文件中只能一个
2.export const obj = [ xxx ] // 一个 js 文件中可以多个,等同于3
3.const obj = [ xxx ]
export { obj }
export { obj2 }
...
import * as common from './common.js' // webpack中加载依赖,common.obj
import {obj, obj2} from './common.js'
十五:forEach 及 for...of 的比较
// forEach进行数组遍历
// 缺点:不能使用breack语句中断循环,不能使用return语句返回到外层函数
// for...in 辣鸡,用来遍历对象属性,且遍历出来的属性还是字符串
// for...of 无敌,规避forEach的缺点,额外支持类数组【DOM】,字符串。
// 缺点:数组的遍历器接口只返回具有数字索引的属性,假如 myArray.foo = 'foo',则无法遍历出来。
for (var value of myArray) {
console.log(value);
}
// 遍历键名
for (let index of ['a', 'b'].keys()) {
console.log(index);
}
// 遍历键值
for (let elem of ['a', 'b'].values()) {
console.log(elem);
}
// 遍历键值对
for (let [index, elem] of ['a', 'b'].entries()) {
console.log(index, elem);
}
十六:apply、call、bind 分析与扩展运算符的替代 (...)
十七:js数组方法forEach、map、filter、reduce、every、some总结
map() // 返回一个新的Array,每个元素为调用func的结果 filter() // 返回一个符合func条件的元素数组 some() // 返回一个boolean,判断是否有元素是否符合func条件 every() //返回一个boolean,判断每个元素是否符合func条件 forEach() //没有返回值,只是针对每个元素调用func reduce() //有返回值,重点是计算数组,返回一个值
1、map速度比forEach快
2、map会返回一个新数组,不对原数组产生影响,foreach不会产生新数组,
3、map因为返回数组所以可以链式操作,forEach不能
十八:不可变性,即创建一个新的副本有利于历史朔源
1.let obj3 = Object.assign({}, obj1, obj2)
2.let obj3 = { ...obj1, obj2 }
3.Array.slice() // 能创建该数组的一个副本
十九:视频初始加载的图片poster
<video class="video" poster="img.png" controls> <source src="video.mp4" type="video/mp4"> </video>
二十:在闭包的海洋里
关于函数作用域:实现【隐藏】最简便的方法就是使用函数封装代码,但这不够彻底——我们必须声明一个函数并调用它。如果这个函数只需要调用一次,我们需要在调用后让这个函数消失,然而使用声明函数封装的方式会始终将函数留在外层作用域中。
function foo() { // doSomething here } foo() //运行后 foo 仍处在全局作用域中
我们需要一个会 自动运行的【无名】函数,即立即执行函数 IIFE
(function foo(msg) { console.log(msg) })(`hello! IIFE`) // ()() 第一个()使得这个函数声明成为一个函数表达式,返回了 foo 函数的引用;此外第二个()实现了函数调用。
()()调用完成后,这个表达式构建的函数没有任何变量引用它,所以会被垃圾回收器回收。
当然函数表达式可以是匿名的,但在这里不推荐使用,因为匿名函数在调式中不会显示出有意义的函数名,不便于理解和调试。
另外IIFE等同于
(function foo(msg) { something here }())
这里说一个闭包的典型 setTimeout 定时器
var timerId | Number = setTimeout(func | code, delay) // tips: code was String, eg: `console.log(1)`;func just was a function name!
var timerId = setTimeout(function(a, b) {}, 100, 1, 1); // 传参给回调
var timerId = setTimeout(function() {myFunc('a', 'b');}, 100);
function func() {} setTimeout(func, 100) // 或者 setTimeout(function() {}, 100) // 或者根据上面的结论给函数表达式添加一个函数名有利无弊端 setTimeout(function timeoutHandler() {}, 100)
setTimeout 在 for 循环中的应用,当你这么写:
for (var i = 0; i < 5; i++) { setTimeout(function(i) { console.log(i); }, i * 1000); } // 你会注意到定时器已经起作用了,只不过每次打出来的是 undefined,因为当执行这个函数的时候,i 已经从循环中跳出,已经没有值了。
所以你改成这样:
for (var i = 0; i < 5; i++) { setTimeout((function(i) { console.log(i); })(i), i * 1000); } // 第一个参数变成了表达式,一个IIFE,它不会等到计时器起作用才执行,而是每次 for 的时候就会执行,所以表现形式就是直接打出了 0,1,2,3,4。注意:并没有起到预期效果,即定时完打印。
解决1:
for (var i = 0; i < 5; i++) { setTimeout((function(i) { return function() { console.log(i); } })(i), i * 1000); } // 虽然第一个参数依旧是IIFE,但IIFE执行完的结果是返回一个函数,这就满足了 setTimeout 对第 1 个参数是函数的要求,并且给定了正确的输入参数,所以达到预期效果。
解决2,推荐:
var j = 0; for (i = 0; i < 5; i++) { setTimeout(function() { console.log(j); j++; }, i * 1000); } // 按照setTimeout标准书写,团队协作间能更易读
还是这个 setTimeout,共享闭包的麻烦
function testLoop(){ for(var i = 0; i < 6; i++){ setTimeout(function printNum(){ console.log(i); },i*1000); } } testLoop(); // 运行testLoop()时执行一个循环,先后六次将PrintNum函数添加到执行队列中,而这6个printNum函数都持有同一个闭包,引用了这个闭包中的变量i。在testLoop函数运行结束之前他们不会有运行的机会,当testLoop函数运行完后i也迭代到了6,这时候第一个PrintNum运行了,他到闭包中寻找变量i,如它所愿它得到了值为6的i,后续的printNum也是一样。
解决:
function testLoop(){ for(var i = 0; i < 6; i++){ (function(j){ setTimeout(function printNum(){ console.log(j); },j*1000); })(i); } } testLoop(); // 在迭代内使用IIFE会为每个迭代都生成一个新的作用域,使得延迟函数的回调可以将新的作用域封闭在每个迭代内部,每个迭代中都会含有一个具有正确值的变量供我们访问——问题解决!