1. Object.entries()和Object.fromEntries()
-
Object.entries() 将对象的属性和值 (键和值) 用数组的形式表现出来。即返回包含对象自身可枚举属性的键值对组成的数组
-
Object.fromEntries() 相当于 Object.entries() 方法的逆操作,将键值对形式的数组转换成对象
const user = {
name: 'andy凌云',
age: 18
};
const toArr = Object.entries(user);
console.log(toArr); // [['name', 'andy凌云'], ['age', 18]]
const toObj = Object.fromEntries(toArr);
console.log(toObj); // { "name": "andy凌云", "age": 18 }
2. 缓存递归
递归(英語:Recursion),又译为递回,在数学与计算机科学中,是指在函数的定义中使用函数自身的方法。通俗的点说呢,就是 方法自己调用自己。 递归思想就是:把问题分解成规模更小,但和原问题有着相同解法的问题。在实际开发过程中,递归有非常多的运用,比如深复制、斐波那契数列、阶乘、求和等等。使用递归,如果不进行缓存优化,超过了最大调用栈就会导致爆栈报错。
// 阶乘
function factorial (n: number): number {
if (n == 1) return n;
return n * factorial(n - 1)
}
console.log(factorial(5)) // 5 * 4 * 3 * 2 * 1 = 120
// 斐波那契数列
function fibonacci (n: number): (number | Function) {
return n < 2 ? n : fibonacci(n - 1) + fibonacci(n - 2);
}
console.log(fibonacci(5)) // 1 1 2 3 5
缓存代理:
function memozie(fn) {
const cache = {};
return function() {
let key = [].slice.call(arguments);
if (cache[key]) {
return cache[key]
} else {
let res = fn.apply(null, arguments);
cache[key] = res;
return res;
}
}
}
function fib(n) {
return n < 2 ? n : fib(n - 1) * n;
}
const fib2 = memozie(fib);
3. 尾递归优化
function sum(n, result = 1) {
if (n <= 1) return result;
return sum(n - 1, result + n);
}
sum(10000);
4. js 可选链操作符(javascript-optional-chaining)使用
可选链操作符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。?. 操作符的功能类似于 . 链式操作符,不同之处在于,在引用为空(null 或者 undefined) 的情况下不会引起错误,该表达式短路返回值是 undefined。与函数调用一起使用时,如果给定的函数不存在,则返回 undefined。 如果不能直接使用, 可通过babel编译器使用
- 语法
obj?.prop
obj?.[expr]
func?.(args)
obj?.['prop' + 'Name']
- 使用介绍
如果我有个对象obj。 现在要访问它的深层属性
baz
const obj = {
foo: {
bar: {
baz: 42,
fun: ()=>{}
},
},
};
// 不使用?.
let baz = obj && obj.foo && obj.foo.bar && obj.foo.bar.baz;
// 使用?.
let baz = obj?.foo?.bar?.baz; // 结果:42
- 可选链不能用于赋值
let object = {};
object?.property = 1; // Uncaught SyntacError: Invalid left-hand side in assignment
- 使用空值合并操作符(
??) 空值合并操作符(??)是一个逻辑操作符, 当左侧的操作数为null或者undefined时, 返回其右侧操作数,否则返回左侧操作数
let customer = {
name: "Carl",
details: { age: 82 }
};
let customerCity = customer?.city ?? "暗之城";
console.log(customerCity); // “暗之城”
- 如果项目不支持, 安装
OC插件 大多数现代浏览器已支持可选链接,为了安全并向后兼容,请使用转换器。如果你使用的是 Babel,请安装 OC 插件...
npm i @babel/plugin-proposal-optional-chaining
并将其添加到你的.babelrc文件中
{
"plugin":[
"@babel/plugin-proposal-optional-chaining",
]
}
- eslint 安装babel编译器后,就可以使用?.操作符了。但是如果你使用eslint的话,你就需要安装babel-eslint来识别这种新语法。
yarn add babel-eslint --dev
然后添加 .eslintrc文件
{
"parser": "babel-eslint",
"rules": {
"strict": 0
}
}
- 在vscode中使用
vscode的js验证器目前并不能识别
?.操作符, 所以会有错误警告:
解决错误警告:
安装vscode扩展eslint, 在扩展商店搜索并安装eslint
修改vscode配置(.vscoe/settings.json):
{
"eslint.alwaysShowStatus": true,
"eslint.autoFixOnSave": true,
"javascript.validate.enable": false, // 主要是这个,关闭vscode的js验证器
"[javascript]": {
"editor.formatOnSave": false,
},
"[javascriptreact]": {
"editor.formatOnSave": false,
},
}
注意: 可选链操作只能在js中使用, 在template模板中需要使用函数方法进行替代操作, 直接使用?.语法会报错
- 解决在template模板使用可选链操作符的办法:
export const chaining = {
install(vue) {
const optionalChaining = (obj, ...rest) => {
let tmp = obj;
for (let key in rest) {
let name = rest[key];
tmp = tmp?.[name];
}
return tmp || "";
}
// 添加实例方法
vue.prototype.$$ = optionalChaining;
}
}
// 在main.js中引入
import chaining from "@/plugins/chaining";
Vue.use(chaining)
// 在template中使用
{{$$(obj, 'first', 'second') }}
- 使用
?.可以进行删除和都操作, 但是不能进行赋值操作 - 参考连接 知乎
5. reduce方法
reduce()方法对数组中的每个元素执行一个由您提供的reducer函数(升序执行),将其结果汇总为单个返回值。 语法:arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])reducer 函数接收4个参数:
- Accumulator (acc) (累计器) 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或
initialValue - Current Value (cur) (当前值) 数组中正在处理的元素
- Current Index (idx) (当前索引) 如果提供了
initialValue,则起始索引号为0,否则从索引1起始 - Source Array (src) (源数组)
您的 reducer 函数的返回值分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值
initialValue可选: 作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错
注意: 如果没有提供
initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始
reduce的一些用法
// 1. 求和, 结果为6
let sum = [0, 1, 2, 3].reduce(function(accumulator, currentValue) {
return accumulator + currentValue;
}, 0);
// 2. 求数组对象里的值, 结果为10
let arr = [{ x: 1 }, { x: 2 }, { x: 3 }, { x: 4 }];
let res = arr.reduce((acc, cur) => {
return acc + cur.x
}, 0); // 10
// 3. 二位数组转一维 [0,1,2,3,4,5];
let arr = [[0, 1], [2, 3], [4, 5]];
let res = arr.reduce((a, b) => {
return a.concat(b)
}, []);
// 4. 将多维数组转化为一维, 结果为 [0, 1, 2, 3, 4, 5, 6, 7]
let arr = [[0, 1], [2, 3], [4, [5, 6, 7]]]
const newArr = function(arr) {
return arr.reduce((pre, cur) => pre.concat(Array.isArray(cur) ? newArr(cur) : cur), [])
}
// 5. 计算数组中每个元素出现的次数, 结果: {Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}
let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
let countedNames = names.reduce(function(allNames, name) {
if (name in allNames) {
allNames[name]++;
}
else {
allNames[name] = 1;
}
return allNames;
}, {});
// 6. 使用扩展运算符和initialValue绑定包含在对象数组中的数组
// friends - 对象数组
// where object field "books" - list of favorite books
let friends = [{
name: 'Anna',
books: ['Bible', 'Harry Potter'],
age: 21
}, {
name: 'Bob',
books: ['War and peace', 'Romeo and Juliet'],
age: 26
}, {
name: 'Alice',
books: ['The Lord of the Rings', 'The Shining'],
age: 18
}];
// allbooks - list which will contain all friends' books +
// additional list contained in initialValue
let allbooks = friends.reduce(function(prev, curr) {
return [...prev, ...curr.books];
}, ['Alphabet']);
// allbooks = [
// 'Alphabet', 'Bible', 'Harry Potter', 'War and peace',
// 'Romeo and Juliet', 'The Lord of the Rings',
// 'The Shining'
// ]
// 7. 数组去重, 结果: [1, 2, 3, 4]
let arr = [1, 2, 3, 4, 4, 1]
let newArr = arr.reduce((pre, cur) => {
if (!pre.includes(cur)) {
return pre.concat(cur)
} else {
return pre
}
}, [])
// 8. 求数组中最大值 结果: 342
const a = [23,123,342,12];
const max = a.reduce(function(pre,cur){return pre>cur?pre:cur;});
// 9. 生成"老大、老二、老三和老四"
const objArr = [{name: '老大'}, {name: '老二'}, {name: '老三'}, {name: '老四'}];
const res = objArr.reduce((pre, cur) => {
if (index === 0) {
return cur.name;
}
else if (index === (arr.length - 1)) {
return pre + '和' + cur.name;
}
else {
return pre + '、' + cur.name;
}
}, '');
// 10. 数组转对象。 按照id生成。
var streams = [{name: '技术', id: 1}, {name: '设计', id: 2}];
var obj = streams.reduce((accumulator, cur) => {accumulator[cur.id] = cur; return accumulator;}, {});
// 11. 求各科成绩的平均值 结果: 88.5
var result = [
{ subject: 'math', score: 88 },
{ subject: 'chinese', score: 95 },
{ subject: 'english', score: 80 }
];
var dis = {
math: 0.5,
chinese: 0.3,
english: 0.2
};
var res = result.reduce((accumulator, cur) => dis[cur.subject] * cur.score + accumulator, 0);