30. array 使用
push()、pop()和unshift()、shift()
这两组同为对数组的操作,并且会改变数组的本身的长度及内容。
不同的是 push()、pop() 是从数组的尾部进行增减,unshift()加元素、shift()弹出元素是从数组的头部进行增减。
29. replace用法
全局替换
'112'.replace(/1/g, function(match) {
console.log(match);
return '3';
});
28. 对象数组
console.log({ 8: 2, 10: 2, a: 3 }['8']); 2
console.log({ 8: 2, 10: 2, a: 3 }[8]); 2
console.log({ 8: 2, 10: 2, a: 3 }.8); error
console.log({ 8: 2, 10: 2, 'a': 3 }.a); 2
console.log({ 8: 2, 10: 2, 'a': 3 }['a']); 2
console.log({ 8: 2, 10: 2, 'a': 3 }[a]); error
console.log(Object.keys({ '08': 2, 10: 2, a: 3 })); ["10", "08", "a"]
console.log(Object.keys([ {'08': 2}, {10: 2}, {a: 3} ])); ["0", "1", "2"]
27. 数组 splice()方法
const arr = [1,2,7,2,6,0,3,1,5,7,8,9,45,12,34,0,56,12,2]
const spliceArr = arr.splice(-5,5)
console.log('spliceArr',spliceArr) // 得到[34,0,56,12,2]
// splice()方法有三个参数,分别表示从哪个下标开始,删几个,新元素。可以实现增加,删除,替换数组元素的功能。arr.splice(-5,5)表示从倒数第五个元素开始,删五个元素。巧妙的是该方法的返回值是删除的元素集合。同时该方法改变了原数组。原数组变成了除了删除的元素剩下的元素集合。
26. 数组 slice()方法
const arr = [1,2,7,2,6,0,3,1,5,7,8,9,45,12,34,0,56,12,2]
const sliceArr = arr.slice(-5)
console.log('sliceArr ',sliceArr) // 得到[34,0,56,12,2]
// slice(start,end)表示从下标start开始到下标end(不包括end)进行截取,得到的是一个新数组,不改变原数组。当start为负值时表示从倒数第几个元素开始往后截取,不填end的话就表示从倒数第几个元素开始截取,一直截取到数组末尾元素。
25. 对象的的方法调用
1. 可用 obj['funtionName'] 很神奇, 所以可以把方法当参数传进去!
例如1、
const groupBy = (arr, func) => arr.map(typeof func === 'function' ? func : val => val[func]);
// map 中传入一个方法体,方法会以数组里面每个对象作为入参,执行返回
groupBy([6.1, 4.2, 6.3], Math.floor);
// map 中传入一个方法名,可以用对象去执行这个方法名
groupBy(['one', 'two', 'three'], 'length');
例如2、
const a = {'one': '1', t:'1'};
console.log(a.one); // 1
console.log(a['one']); // 1
对象里面,直接对象变量,或者对象 字符串,都可以!
24. reduce
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终为一个值,是ES5中新增的又一个数组逐项处理方法,那reduce方法跟foreach、map等数组方法又有啥区别呢。
arr.reduce(callback[, initialValue]) — More From MDN
callback(一个在数组中每一项上调用的函数,接受四个函数:)
previousValue(上一次调用回调函数时的返回值,或者初始值)
currentValue(当前正在处理的数组元素)
currentIndex(当前正在处理的数组元素下标)
array(调用reduce()方法的数组)
initialValue(可选的初始值。作为第一次调用回调函数时传给previousValue的值)
另一些高级用法:https://www.jb51.net/article/132324.htm
1、求和
var arr=[1,2,3,4];
var total=arr.reduce((pre,cur)=>{
return pre+cur;
});
根据定义还可以传初始值
var total=arr.reduce((pre,cur)=>pre+cur,10);
2、计算对象数组的某字段最大值对象
var objArr=[
{"type":"java","count":10},
{"type":"c++","count":20},
{"type":"javascript","count":100},
{"type":"c#","count":10},
{"type":"python","count":30}
]
let maxObj=objArr.reduce((pre,cur)=>{
return pre.count>cur?pre:cur;
});
//返回 {"type":"javascript","count":100}
3、特殊处理
以上面的对象数组为例, 要求返回 var languages='java,c++,javascript,c# 和 python';
var languages=objArr.reduce((pre,cur,index,arr)=>{
if(index===0){ //第一项
return pre+cur.type;
}else if(index=== arr.length-1){ //最后一项
return pre+' 和 '+cur.type;
}
return pre+','+cur.type
},''); //初始值是空字符串
4、一串字符串中每个字母出现的次数?
var arrString = 'abcdaabddcca';
arrString.split('').reduce(function (prev, curr) {
prev[curr] ? prev[curr]++ : prev[curr] = 1;
return prev;
}, []);
// [a: 4, b: 2, c: 3, d: 3]
//某个数在数组中出现的次数
const countOccurrences = (arr, value) => arr.reduce((a, v) => v === value ? a + 1 : a + 0, 0);
countOccurrences([1, 2, 3, 2, 2, 5, 1], 1);
//如果初始值换成对象
var arrString = 'abcdaabddcca';
arrString.split('').reduce(function (prev, curr) {
prev[curr] ? prev[curr]++ : prev[curr] = 1;
return prev;
}, {});
{a: 4, b: 2, c: 3, d: 3}
5、字母游戏
const anagrams = str => {
if (str.length <= 2) { //如果字符串的长度小于等于2
return str.length === 2 ? [str, str[1] + str[0]] : str;
}
return str.split("").reduce((acc, letter, i) => {
return acc.concat(anagrams(str.slice(0, i) + str.slice(i + 1)).map(val => letter + val));
}, []);
}
anagrams("abc"); // 结果会是什么呢?
6、计算数组对象重复个数 (如下:如果code相同,则数量+1)
var list = [
{"date":'2018-08-01',"time":'11:21:20',"code":'11111',"name":'民乐工业园1栋东山口民乐工业',"lng":'112.203909',"lat":'31.021737',"img":'http://192.168.0.12:8080/images/usr/'},
{"date":'2018-08-02',"time":'11:21:20',"code":'11112',"name":'民乐工业园1栋东山口民乐工业',"lng":'112.202104',"lat":'31.023602',"img":'http://192.168.0.12:8080/images/usr/'},
{"date":'2018-08-02',"time":'11:21:20',"code":'11112',"name":'民乐工业园1栋东山口民乐工业',"lng":'112.202104',"lat":'31.023602',"img":'http://192.168.0.12:8080/images/usr/'},
{"date":'2018-08-03',"time":'11:21:20',"code":'11113',"name":'民乐工业园1栋东山口民乐工业',"lng":'112.203909',"lat":'',"img":'http://192.168.0.12:8080/images/usr/'}
];
let obj={}; //通过一个对象来过渡
var filterArr=list.reduce((pre,cur)=>{
if(obj[cur.code]){
obj[cur.code]++;
pre.find(c=>c.code==cur.code).count++;
}else{
obj[cur.code]=1;
pre.push(Object.assign({},{count:obj[cur.code]},cur));
}
return pre;
},[]);
console.log(filterArr);
7、分组
const groupBy = (arr, func) =>
arr.map(typeof func === 'function' ? func : val => val[func]).reduce((acc, val, i) => {
acc[val] = (acc[val] || []).concat(arr[i]);
return acc;
}, {});
groupBy([6.1, 4.2, 6.3], Math.floor);
groupBy(['one', 'two', 'three'], 'length');
8、去重
const assistArray = {};
assetList = assetList.reduce(function(asset, currentAsset) {
if (!assistArray[currentAsset.reservationAssetId]) {
assistArray[currentAsset.reservationAssetId] = currentAsset;
asset.push(currentAsset);
}
return asset;
}, []);
23. 日期
/**
* 返回时间显示类型
* @param {String} end 结束时间
* @return {int} 返回显示类型
*/
getExpireTimeShowType(end) {
const start = moment.now();
if (!end || !start) {
return -1;
}
const startDay = moment(start).format('YYYYMMDD');
const endDay = moment(end).format('YYYYMMDD');
const startYear = moment(start).format('YYYY');
const endYear = moment(end).format('YYYY');
const tomorrowStart = moment(start).add(1, 'days');
const tomorrowStartDay = moment(tomorrowStart).format('YYYYMMDD');
if (startDay === endDay) {
// 当天
return 0;
} else if (tomorrowStartDay === endDay) {
// 明日
return 1;
} else if ((+endDay) > (+startDay) && startYear === endYear) {
// 当年
return 2;
} else if ((+endYear) > (+startYear)) {
// 来年
return 3;
}
return -1;
}
22. CSS 动画
动画一.header-btn-position-show {
top: 91px;
animation: header-btn-position-show 0.3s;
}
@keyframes header-btn-position-show {
0% {top: -111px}
100% {top: 91px}
}
.header-btn-position-hide{
animation: header-btn-position-hide 0.3s;
top: -111px;
}
@keyframes header-btn-position-hide {
0% {top: 91px}
100% {top: -111px}
}
动画二 .header-btn-position {
top: -111px;
transition: all 0.3s;
&.active{
top: 91px;
}
}
constructor(props) {
super(props);
this.state = {
btnShow: false,
}
}
this.setState({
btnShow: false,
})
21.CSS 换行
white-space: normal;
word-wrap: break-word;
word-break: break-all; 一起用
CSS 截断 即不让滚动 overflow: hidden
CSS 不换行 white-space: nowrap;
CSS 省略号 text-overflow:ellipsis;
CSS 从哪边开始显示 text-align
CSS 平分 flex:1 必须要跟 width:0 flex-direction: column;
justify-content: space-between;
20.div 中属性 class 与 className 区别
(https://lark.alipay.com/wl85903/agayyg/zr4m8u)
19.幂等
* 简单来说,一个操作如果具有任意多次执行所产生的影响均与一次执行的影响相同,我们就称之为幂等; * 实际系统中,幂等是一个极为重要的概念。无论是在大型互联网应用还是企业级架构中,我们都见到 REST API 被越来越多的采用。而正确实现幂等,往往是 API 中最难的技术点之一; * 支付重复问题: 那么幂等又该如何实现呢?“多次执行所产生的影响均与一次执行的影响相同”,简而言之,我们需要一个 Dedup(去重)的机制。这往往有很多不同的实现方法,但是有两个很关键的因素:
一是Idempotency Key(幂等令牌)。也就是客户端和服务器端通过什么来识别这实际上是同一个请求,或是同一个请求的多次 retry(尝试)。这往往需要双方又一个既定的协议。往往是类似账单号或者交易 token(令牌)这样一个可以唯一标识同一个请求意愿的元素。通常由客户端生成。
二是Uniqueness Guarantee(确保唯一性)。服务器端用什么机制去确保同一个请求一定不会被处理两次,也就是微信支付怎么确保同一笔交易不会因为客户端发送两次请求就被处理多次。最通常的做法是利用数据库。比如把幂等令牌所在的数据库表的 Column(列)作为 unique indexed。这样,当你试图存储两个含有同样令牌的请求时,必定有一个会报错。注意,简单的读检查并不一定行,因为读与读之间会有 Race Condition(竞争条件),因此还是有可能出错。
参考:(https://baijiahao.baidu.com/s?id=1570246189966333&wfr=spider&for=pc)
这边幂等做法: bff 端每次 产生一个token,给客户端,客户端请求时一定要带给bff端,每次bff端校验对比后,这个token也就失效了,每次新产生一个token 之前的 token 就失效了!这样就达到了幂等的效果
18. js类型合法性校验
(https://www.cnblogs.com/onepixel/p/5126046.html)
17. iframe
是一个内联框架,就是html 中用src方式嵌套另外一个html (https://www.zhihu.com/question/23683645) (http://www.runoob.com/tags/tag-iframe.html)
16.slice
slice() 方法可从已有的数组中返回选定的元素 http://www.runoob.com/jsref/jsref-slice-array.html
slice()方法可提取字符串的某个部分,并以新的字符串返回被提取的部分。
注意: slice() 方法不会改变原始数组
15. charAt() 方法可返回指定位置的字符
14.正则表达式匹配
(http://www.runoob.com/js/js-obj-regexp.html)(http://www.runoob.com/js/js-regexp.html)
(https://www.cnblogs.com/moqing/archive/2016/07/13/5665126.html)
当使用构造函数创造正则对象时,需要常规的字符转义规则(在前面加反斜杠 *\*)。比如,以下是等价的: var re = new RegExp("\\w+");
var re = /\w+/;
**i** - 修饰符是用来执行不区分大小写的匹配。
**g** - 修饰符是用于执行全文的搜索(而不是在找到第一个就停止查找,而是找到所有的匹配)。
m - 执行多行匹配。
全文查找和不区分大小写搜索 "is"
var str="Is this all there is?";
var patt1=/is/gi;
13.Object.assign
用于对象的合并,将源对象( source )的所有可枚举属性,复制到目标对象( target )。
{
**var** target = { a: 1 };
**var** source1 = { b: 2 };
**var** source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
}
注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性
如果只有一个参数,Object.assign会直接返回该参数
如果该参数不是对象,则会先转成对象,然后返回。
由于undefined和null无法转成对象,所以如果它们作为参数,就会报错。
如果非对象参数出现在源对象的位置(即非首参数),那么处理规则有所不同。首先,这些参数都会转成对象,如果无法转成对象,就会跳过。这意味着,如果undefined和null不在首参数,就不会报错
Object.assign拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)
(https://blog.csdn.net/qq_30100043/article/details/53422657)
(https://segmentfault.com/a/1190000011598550)
12.array 方法
(https://www.w3cplus.com/javascript/javascript-array-api.html)
some
测试数组元素时,只要有一个函数返回值为 true,则该方法返回 true,若全部返回 false,则该方法返回 false
canTriggerList.some((item, index) => {
const {
equityType, // 权益类型
} = item;
if (fatigueResults[campId] === true) {
return true;
}
return false;
});
every
使用传入的函数测试所有元素,只要其中有一个函数返回值为 false,那么该方法的结果为 false;如果全部返回 true,那么该方法的结果才为 true
audioSrcResList.every((res, index) => {
if (!(res && res.success && res.result)) {
return false;
}
return true;
});
filter
使用传入的函数测试所有元素,并返回所有通过测试的元素组成的新数组。它就好比一个过滤器,筛掉不符合条件的元素。
list.filter(item => tomorrowStr === item.saleTimeStr)
indexOf
只查询是否有数据,返回下标,空返回 -1
marketTopRes.indexOf(item.productId) < 0
map
遍历数组,使用传入函数处理每个元素,并返回函数的返回值组成的新数组
resultObject.map(({
startDate,
endDate,
}) => ({
reportDate,
reportDateText: moment(reportDate).format('YYYY-MM-DD'),
})),
resultObject.map(({
portfolioOrderId, // 主键,投顾组合单号 String
portfolioName, // 策略名称 String
}) => {
return {
advisorProductId, // 投顾产品id 用于查询机构名称&icon
clientOrderId, // 外部订单号 用于查询记录详情名称
};
});
result.map(item => {
return {
assetTitle: item.assetTitle,
category: item.productCategory,
};
});
resultObject.map(item => item.productId).filter(x => !!x)
reduce
接收一个方法作为累加器,数组中的每个值(从左至右) 开始合并,最终为一个值。{var array = [1, 2, 3, 4]; var s = array.
reduce(function(previousValue, value, index, array){ return previousValue * value; },1); console.log(s); // => 24 // ES6写法更加简洁 array.reduce((p, v) => p * v); // => 24}
forEach
指定数组的每项元素都执行一次传入的函数,返回值为undefined{var array = [1, 3, 5]; var obj = {name:'cc'}; var sReturn = array.forEach(function(value, index, array){ array[index] = value * value; console.log(this.name); // => cc被打印了三次 },obj); console.log(array); // => [1, 9, 25], 可见原数组改变了 console.log(sReturn); // => undefined, 可见返回值为undefined}
find
返回数组中第一个满足条件的元素(如果有的话), 如果没有,则返回undefined
注意 一定要用 !== undefined 去判断
entries
返回一个数组迭代器对象,该对象包含数组中每个索引的键值对 { var array = ["a", "b", "c"]; var iterator = array.entries(); console.log(iterator.next().value); // => [0, "a"] console.log(iterator.next().value); // => [1, "b"] console.log(iterator.next().value); // => [2, "c"] console.log(iterator.next().value); // => undefined, 迭代器处于数组末尾时, 再迭代就会返回undefined }
keys
返回一个数组索引的迭代器 {
var array = ["abc", "xyz"]; var iterator = array.keys(); console.log(iterator.next()); // => Object {value: 0, done: false} console.log(iterator.next()); // => Object {value: 1, done: false} console.log(iterator.next()); // => Object {value: undefined, done: false} }
values
返回一个数组迭代器对象,该对象包含数组中每个索引的值 { var array = ["abc", "xyz"]; var iterator = array.values(); console.log(iterator.next().value); // => abc console.log(iterator.next().value); // => xyz }
排序:
// 排序
// var compare = function(property){
// return function(a,b){
// var value1 = a[property];
// var value2 = b[property];
// return value1 - value2;
// }
// };
// tmpArray = tmpArray.sort(compare('saleTimeStr'));
dataArray = tmpArray.sort(function(a, b){
return a.saleTimeStr - b.saleTimeStr;
});
pingArray[i] = dataArray;
11. put
用于触发 action 。yield put({ type: 'todos/add', payload: 'Learn Dva' });call用于调用异步逻辑,支持 promise 。const result = yield call(fetch, '/todos');
10. Reducer
(https://github.com/dvajs/dva-knowledgemap#put)
http://www.jishux.com/plus/view-725652-1.html
用于处理同步操作,唯一可以修改 state 的地方。由 action 触发。其实一个纯函数
**Effect**
用于处理异步操作和业务逻辑,不直接修改 state,简单的来说,就是获取从服务端获取数据,并且发起一个 action 交给 reducer 的地方
9.object prototype
* 每个函数就是一个对象(Function),函数对象都有一个子对象prototype对象,类是以函数的形式来定义的。prototype表示该函数的原型,也表示一个类的成员的集合,在通过new创建一个类的实例对象的时候,prototype对象的成员都成为实例化对象的成员。 * prototype 属性使您有能力向对象添加属性和方法 (http://www.w3school.com.cn/jsref/jsref_prototype_array.asp)
8. redux
8.1(http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html)
8.2(http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_two_async_operations.html)
8.3(http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_three_react-redux.html)
7. flux
一种前端的应用架构(http://www.ruanyifeng.com/blog/2016/01/flux.html) (阮老师书籍)
1. 核心架构思想:
flux 将应用分成四个部分
view: 视图层,纯显示作用
action: 响应事件,感应用户操作
dispatcher: 事件派发器,执行回调函数,应只有派发逻辑
store: 数据存储,一旦变化,更新view
2. 数据传递流向:
view/action->action->dispatcher->store->view
特点:任何相邻部分 数据都是单项流动
1. 用户访问 View
2. View 发出用户的 Action
3. Dispatcher 收到 Action,要求 Store 进行相应的更新
4. Store 更新后,发出一个"change"事件
5. View 收到"change"事件后,更新页面
6. babel
语法检测 基本介绍
https://lark.alipay.com/wb-yjs345021/yjson/eg23m6
配置:
[https://lark.alipay.com/minhui.lmh/tools/babel-tips]
http://www.ruanyifeng.com/blog/2016/01/babel.html
5. tnpm
1. 封装扩展npm,具体用法:
[http://web.npm.alibaba-inc.com/package/tnpm]
4. npm
对node.js 模块管理工具 [https://lark.alipay.com/alinode/handbook/tnpm]
3. package.json
scripts: 声明一系列npm脚本指令
dependencies: 项目在生产环境中依赖的包
devDependencies: 项目在开发和测试环境中依赖的包
[https://www.cnblogs.com/tzyy/p/5193811.html]
2. 浏览器debug
1. 查看所有错误 localStorage.debug="*"
2. 查看网络地址 location.href
3. hosts 配置 sudo vi /etc/hosts
4. 控制台终端terminal 注意一定要在英文输入法下
5. 查看端口 是否被占用 lsof -nP -iTCP -sTCP:LISTEN
6. kill -9 26737 杀掉进程
7. tail -f *.log 跟踪文件变化
8. ssh 用法 https://www.jianshu.com/p/10023495fba9
9. sudo 用法 https://www.jianshu.com/p/d5f9672f94ef
10. grep 用法 https://www.jianshu.com/p/652b4975b242
https://www.jianshu.com/p/1990a4561602
1. 显示隐藏文件
defaults write com.apple.finder AppleShowAllFiles -boolean true