[前端]javascript你不一定知道的进阶(干货)实用技巧.

3,473 阅读6分钟

首先说明一下:我这里不举最基础的例子,各位大佬已经讲烂了,比如这位 还有这位,我只讲述最实用最常用的例子,你拷贝完,就能用的例子

本文章参照做过的业务,实打实的进阶讲述,你能用他们干什么,项目中应该怎么运用?这个就要各位往看下了.

数组获取最后一位

const list =[1,2,3,4,5,6,7,8,9]

list.at(-1) //9
list.at(0)   //1

数组对象判断是否存在指定值

const list = [
	  { name: '头部导航', backward: false },
	  { name: '轮播', backward: true },
	  { name: '页脚', backward: false },
];

    const someBackward = list.some(item => item.backward);
    // someBackward: true
    const everyNewest = list.every(item => !item.backward);
    // everyNewest: false
  • 二者都是用来做数组条件判断的,都是返回一个布尔值
  • 二者都可以被中断
  • some 若某一元素满足条件,返回 true,循环中断;所有元素不满足条件,返回 false。
  • every 与 some 相反,若有益元素不满足条件,返回 false,循环中断;所有元素满足条件,返回true。

数组去重

这是一个原生的JS函数但是非常简洁,Set接受任何可迭代对象,如数组[1,2,3,3],并删除重复项

let a=[1,1,1,2,3,4,5,5,5,]
[...new Set(a)] 
//[1, 2, 3, 4, 5]

数组对象去重

//方式一
var obj = {};
  arr = arr.reduce(function(item, next) {
   obj[next.key] ? '' : obj[next.key] = true && item.push(next);
   return item;
  }, []);
  console.log(arr);
// 方式二 使用 lodashjs
_.uniqBy([{user_id:3},{user_id:3}],'user_id')  //[{user_id:3}]

数组分割

function Chunk(arr = [], size = 1) {
    return arr.length ? arr.reduce((t, v) => (t[t.length - 1].length === size ? t.push([v]) : t[t.length - 1].push(v), t), [[]]) : [];
}
const arr = [1, 2, 3, 4, 5];
Chunk(arr, 2); // [[1, 2], [3, 4], [5]]

数组求最大或最小值

function Max(arr = []) {
    return arr.reduce((t, v) => t > v ? t : v);
}

function Min(arr = []) {
    return arr.reduce((t, v) => t < v ? t : v);
}

const arr = [12, 45, 21, 65, 38, 76, 108, 43];
Max(arr); // 108
Min(arr); // 12

展开多维数组

flat()    
flatMap()
  • flat() 方法可以将多维数组展平成一维数组
  • 请注意,如果提供的数组中有空值,它们会被丢弃:
  • flat() 还接受一个可选参数,该参数指定嵌套数组应该被展平的级别数。 如果未提供参数,则将使用默认值1:如果输入Infinity参数则不管多少维数组都会展平
  • flatMap() 方法将map()和flat()组合成一个方法。 它首先使用提供的函数的返回值创建一个新数组,然后连接该数组的所有子数组元素。 来个例子:\

遍历对象或数组对象

Object.entries()函数返回一个给定对象自身可枚举属性的键值对的数组。 这个真的很有用。之前为了遍历key和value搞得很烦。

for(let [key,value] of Object.entries(obj1)){
	console.log(`key: ${key} value:${value}`)
}
//遍历对象
//key:a value:1
//key:b value:2
//key:c value:3

//遍历数组对象
//key:0 value:{a: 1, b: 2, c: 3}
//key:1 value:{a: 1, b: 2, c: 3}

将二维数组转换对象

Object.entries是把对象转成键值对数组,而Object.fromEntries则相反,是把键值对数组转为对象

const arr = [
  ['name', '松鼠'],
  ['age', 22],
  ['gender', '男']
]
console.log(Object.fromEntries(arr)) 
// { name: '松鼠', age: 22, gender: '男' }

将一维数组转换为对象

var plants = ['Saturn', 'Earth', 'Uranus', 'Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter'];
var plantsObj = {...plants }
console.log(plantsObj); // {'0': 'Saturn','1': 'Earth', '2': 'Uranus','3': 'Mercury','4': 'Venus','5': 'Earth','6': 'Mars','7': 'Jupiter'}

数组的快速查找

使用Array的find()可以实现快速查找。

 const pets=[  
        {type:'Dog',name:'Max'},  
        {type:'Cat',name:'Karl'},  
        {type:'Dog',name:'Tommy'}  
    ]  
let pet= pets.find(pet=>pet.type==='Dog'&&pet.name==='Tommy');  
console.log(pet);
// {type: "Dog", name: "Tommy"}

findLast()和findLastIndex() 可以从尾到头搜索数组
['a1', 'b', 'a2'].findLast(x => x.startsWith('a')) // 'a2' 
['a1', 'b', 'a2'].findLastIndex(x => x.startsWith('a')) // 2

求两个数组的交集

要求两个数组的相同值,首先确保数组不重复,然后使用filter()方法和includes()方法。

var plants1 = ['Saturn', 'Earth', 'Uranus', 'Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter'];
var plants2 = ['Saturn', 'Earth', 'Uranus'];
var alonePlants = [...new Set(plants1)].filter(item => plants2.includes(item));
console.log(alonePlants); 
// [ 'Saturn', 'Earth', 'Uranus' ]

获取数组最后一个元素

var arr = [1,2,3,4,5]
arr.pop() //5 此方法会改变数组的结构,不推荐
arr[arr.length - 1] //5 常用方法
arr.slice(-1)[0] //5 不需要计算数组的长度,直接拿到最后一个元素
arr.at(-1)    // 5  原生新语法

动态为对象的属性指定键名

const dynamic = 'email';
let user = {
    name: 'John',
    [dynamic]: 'john@doe.com'
}
console.log(user);// outputs { name: "John", email: "john@doe.com" }

取出数组对象中的指定属性值,并返回为数组

const sheet=[ {type:'Dog',name:'Max'}, {type:'Cat',name:'Karl'}, {type:'Dog',name:'Tommy'} ]
  let arr =sheet.map((v,i)=>{
      return v['name']
    }}

过滤数组对象中的指定内容,同时做出修改,并返回为新数组

flatMap遍历数组每一项,遍历过程中可以对当前项增删查改修饰然后返回,注意返回的是当前项数组类型,得到一个新的数组,不改变原数组(可以理解为是filter和map的结合体)

回调参数

遍历数组元素的时候,会为每一个元素都执行一次回调函数,可以传入三个参数:

  1. currentValue:当前正在数组中处理的元素。
  2. index:可选的。数组中正在处理的当前元素的索引。
  3. array:可选的。调用flatMap方法的数组。

flatMap能用于在遍历数组期间增加、删除和修改数组元素(也就是修改 items 的数量),当我们需要增加元素时,就在回调函数中返回一个包含多个元素的数组,如果想要删除某一个元素时,就在回调函数中返回一个空数组(注意是空数组,返回空字符串、null或者undefined都不会改变数组items 的数量),如果想要修改元素,则在回调函数中返回一个修改过后的元素即可。

let arr = [
  { id1value:'测试1' },
  { id2value:'测试2' },
  { id3value:'测试3' },
]
// 1、传统思维方式
const newArr = arr.filter(i=>{
        return i.id>1
}).map(c=>({
        return {id:c.id*10,newValue:c.value}
}));
// 2、 使用flatMap方法
const newArr = arr.flatMap((item)=>{
  return  item.id>1?[{id:item.id*10newValue:item.value}]:[]
});
//[
//  {id: 20, newValue: '测试2'}
//  {id: 30, newValue: '测试3'}
//]

//用途
1. 删除数组元素
2. 修改元素

3. 交叉循环
var a = [1,2,3]\
var b = [3,4]\
a.map(a => (b.map(o => [a,o])))\
// [ [[1,3],[1,4]], [[2,3],[2,4]], [[3,3],[3,4]] ]

a.flatMap(a => (b.map(o => [a,o])))\
// [ [1,3],[1,4],[2,3],[2,4],[3,3],[3,4] ]
// 区别就是flatMap少嵌套了一层

获取URL的查询参数

用最精简的代码

//第一种
q={};
location.search.replace(/([^?&=]+)=([^&]+)/g,(_,k,v)=>q[k]=v);
console.log(q); 
{
    "ie": "utf-8",
    "f": "8",
    "rsv_bp": "1",
    "tn": "baidu",
    "wd": "js%E6%97%A0%E7%A9%B7%E5%A4%A7",
    "oq": "%25E6%2597%25A0%25E7%25A9%25B7%25E5%25A4%25A7",
    "rsv_pq": "ac0117fa00057293",
    "rsv_t": "90bbevB0RLfLUZ4XME2%2FGHL2Uad8MPo%2Bhvu89MbGddXhQ4jpzIZRmNBfuIs",
    "rqlang": "cn",
    "rsv_enter": "1",
    "rsv_btype": "t",
    "rsv_dl": "tb",
    "inputT": "1127"
}

//第二种
Object.fromEntries(new URLSearchParams(window.location.href))

//第三种

function getUrlKey(keyname) {
  try {
    return decodeURIComponent((new RegExp('[?|&]' + keyname + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [])[1].replace(/\+/g, '%20')) || null
  } catch {
    return undefined
  }
}
//https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&tn=baidu&rsv_pq=9305ba5d0001e69a&rsv_t=2a28eHKWqUiNWG6ZvxxZWgyGZVTVtHq6Y%2FRCYC0mZIGDvXBxyKYChEFWC70&rqlang=cn&rsv_dl=tb&rsv_enter=1&rsv_btype=t&inputT=4625&rsv_sug3=12&rsv_sug1=11&rsv_sug7=100&rsv_sug2=0&rsv_sug4=6361

getUrlKey('tn') //baidu

字符串内网址替换a标签

function getHref(content) {
		if (!content) {
			return "";
		}
		let urlPattern = /(https?:\/\/|www\.)[a-zA-Z_0-9\-@]+(\.\w[a-zA-Z_0-9\-:]+)+(\/[\(\)~#&\-=?\+\%/\.\w]+)?/g;
		content = content.replace(urlPattern, function(match) {
			var href = match;
			if (match.indexOf("http") == -1) {
				href = "http://" + match;
			}
			return "<a target=\"_blank\" href=\"" + href + "\">" + match + "</a>";
		});
		return content;
}

删除树形结构数据里的空节点

树形数据,最深层的children都是[ ],全删掉之后,外层的children也变成[ ]了,然后继续删除,直至所有children为[ ]的子节点都删除。

//原数据,删除children为空的节点
 let b=[
    {
        "id": 24,
        "name": "部门",
        "children": [
            {
                "id": 25,
                "name": "子部门",
                "children": [
                    {
                        "id": 30,
                        "name": "小组",
                        "children": [
                            {
                                "name": "张三",
                                "id": 51,
                                "user_id": 123456,
                            }
                        ]
                    }
                ]
            },
            {
                "id": 32,
                "name": "部门1",
                "children": []
            }
        ]
    },{
        "id": 25,
        "name": "部门1",
        "children":[]
    }
 ]
//方法
function deleteGroup(treeData) {
    function traversal(data) {
      for (let i = 0; i < data.length; i++) {
        const info = data[i]
        if (info.children) {
          if (info.children.length > 0) {
            traversal(info.children)
          }
          if (info.children.length === 0) {
            data.splice(i, 1)
            i--
          }
        }
      }
    }
    traversal(treeData)
  }
deleteGroup(b)

//结果
[
    {
        "id": 24,
        "name": "部门",
        "children": [
            {
                "id": 25,
                "name": "子部门",
                "children": [
                    {
                        "id": 30,
                        "name": "小组",
                        "children": [
                            {
                                "name": "张三",
                                "id": 51,
                                "user_id": 123456
                            }
                        ]
                    }
                ]
            }
        ]
    }
]

获取对象类型

function getType(value){
    return Object.prototype.toString.call(value).slice(8,-1).toLowerCase()
}
getType({a:1})  //object
getType([666])   //array
getType('123')   //string
getType(new FormData())  //formdata
getType(new Date())     //date
getType(new Date().getTime())   //number
getType(new Map())            //map

vue 样式穿透

[@vue/compiler-sfc] ::v-deep usage as a combinator has been deprecated. Use :deep(<inner-selector>) instead.

竟然说>>>和/deep/和 ::v-deep 已经被弃用了,这变化是真的快啊,虽然样式仍然生效,但是编译报警告这也太难受了

//警告例子
<style scoped>
 ::v-deep .box p:{ //使用 ::v-deep进行穿透
     color:red
 }

/deep/ .main{
    background: #df2929;
}
>>> .main{
    background: #df2929;
}
 
</style>
 
 
//正确例子
<style scoped>
 
:deep(.main){
    background: #df2929;
}
 
</style>

Element UI 表单校验进阶知识

element UI表单校验,他不香吗?