(1)、数组的遍历
1、for of
2、for in
3、forEach 空数组不报错
4、map
5、Object.keys
(2)、对象的遍历
const obj = { id:1, name:'zhangsan', age:18 }
1、for in for(let key in obj){ console.log(key + '---' + obj[key]) }
2、Object.keys(obj) // 遍历对象的key console.log(Object.keys(obj)) //['id','name','age']
3、Object.values(obj)// 遍历对象的value console.log(Object.values(obj)) //['1','zhangsan','18']
4、Object.getOwnPropertyNames(obj) Object.getOwnPropertyNames(obj).forEach(function(key){ console.log(key+ '---'+obj[key]) })
(3)、for of
遍历可迭代对象定义要迭代的数据 遍历出value 常用于数组遍历!!!! 用于array,string,typedArray,map,set,不能用于遍历对象
(4)、for in
任意顺序迭代对象的可枚举属性 可以遍历出key和value 常用于对象遍历,也可以遍历数组!!!!
var obj = {a:1, b:2, c:3}; for (var prop in obj) { console.log("obj." + prop + " = " + obj[prop]); }
数组函数
纯函数: 1、不改变源数组(没有副作用);2、返回一个数组
1、非纯函数 pop、push、shift、unshift、forEach、some、every、reduce,splice(剪接) 2、纯函数 concat、map、fliter、slice(切片)
const res = [10, 20, 30].map(parseInt)
console.log(res)
// 拆解
[10, 20, 30].map((num, index) => {
return parseInt(num, index)
})
forEach
某天尝试了下在 forEach函数中调用 await Promise() 方法,如下:
var arr = [1,2,3]
arr.forEach(async (v,i,a)=>{
await Promise()
})
发现并没有按照想象中等到上一个Promise 处理完成后再执行下个Promise。
经过查阅资料后发现,实际forEach函数内部是异步的,遇到这种问题请使用for循环,如下:
var arr = [1,2,3]
for(let i=0;i<arr.length;i++){
await Promise()
}
取两个二维数组的差异项
let diff = this.extractInfoTmp.filter(a =>
!this.lastExtractInfoTmp.some(a2 => a.length === a2.length && a2.every((n, i) => n === a[i]))
)
删除数组元素
const array = ["a", "b", "c", "d"]
const part = array.splice(0, 2) // part为["a", "b"] array为['c', 'd']
获取数组最后一项
const arr = [1, 2, 3, 4, 5];
const part = arr.slice(-1) // part为[5] arr不变
类数组转数组
const fn = function(){
console.log(arguments)
}
Array.prototype.slice.call(arguments);
**`slice()`** 方法返回一个新的数组对象,这一对象是一个由 `begin` 和 `end` 决定的原数组的**浅拷贝**(包括 `begin`,不包括`end`)。
beigin和end都没写的时候就返回整个所有数据,原始数组不会被改变。
[...arguments]
对象动态属性
const dynamic = 'color';
var item = {
brand: 'Ford',
[dynamic]: 'Blue'
}
console.log(item); // { brand: "Ford", color: "Blue" }
对象判空
Object.keys({}).length // 0
Object.keys({key: 1}).length // 1
转换成布尔值
!!undefined // false
!!"996" // true
!!null // false
!!NaN // false
推荐使用 switch case 而不是 if...else if...
函数参数过多 推荐使用对象传参
重命名as 只能在 export 或 import时使用
// util.js
function add(a, b) {
return a + b;
}
export { add as addFn};
// main.js
import { addFn as add } from './util.js'
console.log(add) // add(a, b) { return a + b; }
js精度问题
事情的缘故是 前端用户输入了 32849.27 这个金额。可能是接口约定要接收厘单位的,所以前端x1000. 结果因为js的精度问题。 传给后端的是32849269.999999996
- 涉及到金额的计算一定要让后端做,前端只做展示不做金额和数据的计算。切记。
- 对于约定是整数或者固定位数的小数的形式,要么是用专业的金额计算库,要么用toFixed(0)兜底一下,toFixed也不是那么可靠但大部分情况适用。用bignumber.js处理
3、
那么JavaScript在计算0.1+0.2时到底发生了什么呢?
首先,十进制的0.1和0.2会被转换成二进制的,但是由于浮点数用二进制表示时是无穷的:
0.1 -> 0.0001 1001 1001 1001...(1100循环)
0.2 -> 0.0011 0011 0011 0011...(0011循环)
复制代码
IEEE 754 标准的 64 位双精度浮点数的小数部分最多支持53位二进制位,所以两者相加之后得到二进制为:
0.0100110011001100110011001100110011001100110011001100
复制代码
因浮点数小数位的限制而截断的二进制数字,再转换为十进制,就成了0.30000000000000004。所以在进行算术计算时会产生误差。
js 函数 值传递与引用传递
说出下面运行的结果,解释原因。
function test(person) {
person.age = 26
person = {
name: 'hzj',
age: 18
}
return person
}
const p1 = {
name: 'fyq',
age: 19
}
const p2 = test(p1)
console.log(p1) // -> ?
console.log(p2) // -> ?
复制代码
结果:
p1:{name: “fyq”, age: 26}
p2:{name: “hzj”, age: 18}
复制代码
原因: 在函数传参是
引用类型,传递的是对象在堆中的内存地址值,test函数中的实参person是p1对象的内存地址,通过调用person.age = 26确实改变了p1的值,但随后person变成了另一块内存空间的地址,不再指向外面的p1,并且在最后将这另外一份内存空间的地址返回,赋给了p2。 如果传给函数的是值类型如num,那么会复制一份num给函数用,与外面的num无关
执行顺序
声明fn = () => {}的时候 只会知道fn等于一个函数,不会执行函数中的内容 声明 a = 1 +2 的时候会执行 1+ 2
const fn = () =>
new Promise((resolve, reject) => {
console.log(1);
resolve("success");
});
console.log("start");
fn().then(res => {
console.log(res);
});
start
VM141:3 1
VM141:8 success
Promise {<fulfilled>: undefined}
const a = 1 + 2
//a 3