js 遍历 和 数组函数 及其他常用方法

173 阅读4分钟

(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

  1. 涉及到金额的计算一定要让后端做,前端只做展示不做金额和数据的计算。切记。
  2. 对于约定是整数或者固定位数的小数的形式,要么是用专业的金额计算库,要么用toFixed(0)兜底一下,toFixed也不是那么可靠但大部分情况适用。用bignumber.js处理

3、image.png

那么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。所以在进行算术计算时会产生误差。

juejin.cn/post/684490…

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