日常记录

116 阅读5分钟

1. 尾调用

指某个函数的最后一步是调用另一个函数,只要最后一步不是调用函数,就不属于尾调用。

例如:
function f(x){
  return g(x);
}

2. 尾递归

函数调用自身,称为递归。如果尾调用自身,就称为尾递归。递归好用内存较大,容易"栈溢出"错误,而尾递归只存在一个调用记录,所以永远不会发生"栈溢出"错误。

例如:
function factorial(n, total) {
  if (n === 1) return total;
  return factorial(n - 1, n * total);
}
factorial(5, 1)

3. map数据类型(key,value模式)

map是一组键值对的结构,具有极快的查找速度。

let map = new Map(['张三',67],['李四',89],['王五',92])
map.set('赵六', 67); // 添加新的key-value
map.has('赵六'); // 是否存在key '赵六' => true
map.get('赵六'); // 取值:=>67
map.delete('赵六'); // 删除key '赵六'
map.clear()   //清空所有

1.生成 keys 的数组

[...map.keys()]

2.生成 values 的数组

[...map.values()]

3.生成键值对的数组

[...map.entries()] // [[1,"xxx"], [2, "yyy"]]

4. set数据类型(key)

一组key的集合,但不存储value。而且key不能重复,Set 没有 map, filter,需要先转换成为数组。

set本身是一个构造函数 把 Set 转成 Array

1.Array.from
2.拓展运算符 [...set]

var set = new Set([1, 2, 3, 3, '3']);
    set =  {1, 2, 3, "3"}
   3'3'不是相同元素
    set.add(3) //增加新的key,如果重复添加不会生效

Set 常用于数组去重;Map 是为了解决对象非字符串不能作为 key 的问题

5. for in,for of,forEach,map,filter,find

for in

遍历对象,for...in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。

let obj = {
        name:"张三",
        age:21,
        work:"前端"
    }
    
for (let index in obj) {
    console.log("key为---",index,"val为---",obj[index])
}

//输出 key为---name val为---张三

for of

可以与break、continue和return配合使用,只循环集合本身的元素

    var a = ['A' ,  'B' ,  'C'];

    a.name =  'Hello';

    for(var x of a) {
        //只循环集合本身的元素
        console.log('A','B', 'C')

    }

foreach(不生成新数组,也不改变原数组)

无法跳出循环,break命令或return命令都不能奏效。 会从头到尾对数组里的每个元素遍历一遍,他不会生成新数组,也不改变原数组,回调函数接收三个值,分别是 数组的元素,索引和当前数组

 let arr = ["a","b","c","d"]
    arr.forEach((el,index,array) => {
        if(el == "b" ) return
        console.log(el,index,array)
    })

在上边的例子中我加了一个判断,如果满足元素等于b,return出去,按理说遍历时满足这个条件后边就不遍历了,但是foreach不会,他会接着向下进行把每个元素遍历一遍。

map(不修改原数组,返回新数组)

和foreach类似,map也会把数组的每一项都遍历一遍,他会返回一个新数组,但是原数组保持不变,值得注意的是,map不会对空数组进行检测

let arr = [1,2,3,4,5]
let  b =  arr.map((el,val,array) => {
   return el = el*2
})
//输出 [2,4,6,8,10]

filter(不修改原数组,返回新数组)

filter为过滤的意思,也就是说它会把满足条件的元素拿出来形成一个新的数组

let arr = [1,2,3,4,5,6,7,8,9]
let result = arr.filter(el => {
    return el % 2 == 0
})
//输出 [2,4,6,8]

巧妙的运用filter去除数组中重复的元素:

let phone = ['苹果','锤子','三星','华为','锤子','苹果','小米','锤子']

let result = phone.filter((el,index,arr) => {

  return arr.indexOf(el) == index

})

//输出 ["苹果", "锤子", "三星", "华为", "小米"]

find(不修改原数组,返回查找到的值)

array.find(function(currentValue, index, arr),thisValue),其中currentValue为当前项,index为当前索引,arr为当前数组,thisValue为匹配值

1.find() 方法返回通过测试(函数内判断)的数组的第一个元素的值。

2.如果没有符合条件的元素返回 undefined

3.find() 对于空数组,函数是不会执行的。

4.find() 并没有改变数组的原始值。

let test = [1, 2, 3, 4, 5];
let a = test.find(item => item > 3);
console.log(a); //4,查找到第一个匹配的就不在继续查找

let b = test.find(item => item == 0);
console.log(b); //undefined

6. Object.assign(targetObj1(目标对象), sourceObj1(源), sourceObj2(源));

如果目标对象有重名的会覆盖前面的属性

let targetObj1 = { a: 1 };
let sourceObj1 = { b: 1 };
let sourceObj2 = { c: 3 };
Object.assign(targetObj1, sourceObj1, sourceObj11);
console.log(targetObj1);  //输出 {a: 1, b: 1, c: 3}

4覆盖1,5覆盖2,因为它们在数组的同一位置,所以就对应位置覆盖了

console.log(Object.assign([1, 2, 3], [4, 5])); //输出[4,5,3]

可以合并多个对象

let target = {
        a:33,
        b:44
    }
let sources = {
    c:55,
    d:66
}
const merge = (target, ...sources) => Object.assign(target, ...sources);
console.log(merge(target,sources)) // {a: 33, b: 44, c: 55, d: 66}

浅拷贝

let obj = {a:1,b:2}
let obj1 = Object.assign(obj,{c:4,d:5})

深拷贝

let obj1 = Object.assign({}, obj); // obj赋值给一个空{}
    obj1.a = 3;

7. 扩展运算符(…)

用于取出参数对象中的所有可遍历属性,拷贝到当前对象之中

let bar = { a: 1, b: 2 }; 
let baz = { ...bar }; // { a: 1, b: 2 }

const arr1 = [1, 2]; 
const arr2 = [...arr1]; // [1,2]

//扩展运算符可以与解构赋值结合起来,用于生成数组
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1 
rest // [2, 3, 4, 5]

如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。

const [...rest, last] = [1, 2, 3, 4, 5]; // 报错 
const [first, ...rest, last] = [1, 2, 3, 4, 5]; // 报错

扩展运算符还可以将字符串转为真正的数组

[...'hello'] 
// [ "h", "e", "l", "l", "o" ]