js中的奇技 * 巧
函数设置参数的默认值
let a = "如果没传我是a"
function fn(str=a){
console.log(str)
}
fn("我传了,所以我是b")
检测类型
Object.prototype.toString.call('类型')
数组对象去重
let obj1 = [
{ name: 121, id: 1231 },
{ name: 123, id: 1231 },
{ name: 123, id: 1231 },
]
let newObj = {}
const data = obj1.reduce((init,next) => {
newObj[next.name] ? '' : newObj[next.name] = true && init.push(next)
return init;
}, [])
**去除两个不同对象不同字段相同的值**
```javascript
let obj1 = [
{ name: 121, id: 1231 },
{ name: 123, id: 1231 },
{ name: 123, id: 1231 },
]
let obj2 = [
{ age: 163, id: 1231 },
{ age: 13, id: 1231 },
{ age: 12, id: 1231 },
{ age: 123, id: 1231 },
]
const data = obj1.filter((item) => !obj2.some((value) => item.name === value.age))
从对象解构出数据
let obj = {a: 11, b: 12}
let {a} = obj
console.log(b)
//直接解构出参数对象的数据
function fn({a, b}){
console.log(a, b)
}
fn({a:123,b:456})
动态拼接地址参数
const queryUrl = 'https://www.baidu.com/abc.html'
const params = {
type?: ‘类型’,
name?: '姓名’
}
Obj.keys(params).forEach((key) => {
const and = queryUrl.indexOf('?') >= 0 ? '&' : '?' ;
if(params[key]){
queryUrl + = `${and}${key}=${params[key]}`;
}
})
export default导出对象有如下特点:
可不必须指定函数名、类名等
在一个文件或模块中,export、import 可以有多个,export default 仅有一个
export default 向外暴露的成员,可以使用任意变量来接收
export default 向外暴露的成员,import时不需要用大括号嵌套,也不能用大括号嵌套
箭头函数的简写
const fn = a => a + 4
console.log(fn(1)) /* 输出5 */
分割数组
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
function setArr(arr, size) {
let newArr = []
for (let i = 1; i < arr.length; i++) {
newArr.push(arr.slice(i, i+=size))
}
return newArr
}
console.log(setArr(arr, 4))
递归实现深拷贝
function copy(obj){
let newobj = null; //声明一个变量用来储存拷贝之后的内容
//判断数据类型是否是复杂类型,如果是则调用自己,再次循环,如果不是,直接赋值即可,
//由于null不可以循环但类型又是object,所以这个需要对null进行判断
if(typeof(obj) == 'object' && obj !== null){
//声明一个变量用以储存拷贝出来的值,根据参数的具体数据类型声明不同的类型来储存
newobj = Array.isArray(obj) ? [] : {};
//循环obj 中的每一项,如果里面还有复杂数据类型,则直接利用递归再次调用copy函数
for(var i in obj){
// 每次循环都会判断递归一次 一直到拷贝的是普通类型跳出递归
newobj[i] = copy(obj[i])
}
}else{
newobj = obj
}
return newobj; //函数必须有返回值,否则结构为undefined
}
obj.hasOwnProperty()
hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中(非继承属性)是否具有指定的属性, 如果 object 具有带指定名称的属性,则 hasOwnProperty 方法返回 true,否则返回 false。此方法不会检查对象原型链中的属性;该属性必须是对象本身的一个成员
Object.keys(obj)
let obj = {a:2,b:3,c:"星期一",d:()=>{console.log("这是函数")}}
// 拿到对象的键,组成一个新数组
console.log(Object.keys(obj))
数组的解构赋值
1:ES6允许按照一定模式从数组跟对象中提取值,然后对变量进行赋值。这被称为解构
2:从数组中提取值,按照对应位置对应赋值
let [a,b,c]=[1,2,3]
console.log(a) //1
console.log(b) //2
console.log(c) //3
防抖
let inp = document.getElementById("box")
//input 执行的是dobounce的返回值 (返回值是一个函数)
inp.oninput = dobounce(function () {
console.log(111)
}, 500)
function dobounce(fn, time) {
let t = null;
return function () {
if (t !== null) {
clearInterval(t)
}
// 第二次清除了上一次的计时器, 开启新的计时器,如果不调用的话直接出结果,如果调用继续循环删除上一次,再次调用...
t = setTimeout(() => {
fn()
}, time)
}
}
节流
function reduce(fn, delay) {
let timer = null
return function () {
if (timer) { return }
timer = setTimeout(function () {
fn()
timer = null;
}, delay)
}
}
promise解决异步
function fn(){
let data = new Promise((resolve, reject) => {
setTimeout(()=>{
var num = Math.ceil(Math.random()*10);
if(num<=5){
resolve(num);
}
else{
reject('数字太大了');
}
}, 2000)
})
return data
}
fn().then(data => {
console.log(data)
})
数组对象去重
var points = [{
lat: 22.687,
lng: 114.014
}, {
lat: 22.687,
lng: 112.004
}, {
lat: 22.837,
lng: 114.014
}];
var result = [];
var obj = {};
for (var i = 0; i < points.length; i++) {
if (!obj[points[i].lat]) {
// 判断obj有没有obj.22.687 如果没有将数据存入数组 然后给obj.22.687 添加一个属性
// 下次再次循环如果数组有相同的数据 再次判断obj.22.687时就直接false 不走这一步
// 依次遍历数组
result.push(points[i]);
obj[points[i].lat] = 1;
}
}
console.log(obj);
原生对象中的get 和 set 方法
// get:指读取属性时调用的函数。
// set:指写入属性时调用的函数。
let te = [{a:true},{a:true},{a:true},{a:true},{a:true},{a:true}]
let tescT = false
let obj = {
get age(){
tescT = te.every((e)=> e.a)
// 如果全部都是true 就给假设的全选设置为true
},
set age (v){
// 如果改变假设全选的false 全部都改为false
console.log("我把所有的单选变成了选中",v)
}
}
obj.age = true
console.log(obj.age)
console.log(tescT)
Es6的Generator
function *fn(){
yield console.log(1);
yield "b";
return "a"
yield "c";
}
var h = fn()
console.log(h.next())
console.log(h.next()) //执行当前方法或者返回当前数据在对象value
console.log(h.next()) //done的值从这开始都改为负数
console.log(h.next()) //如果先执行return 后面暂停结果则不输入
Object.is(value1, value2);
Object.is() 判断两个值是否相同。如果下列任何一项成立,则两个值相同:
两个值都是 undefined
两个值都是 null
两个值都是 true 或者都是 false
两个值是由相同个数的字符按照相同的顺序组成的字符串
两个值指向同一个对象
两个值都是数字并且
都是正零 +0
都是负零 -0
都是NaN
都是除零和 NaN 外的其它同一个数字
这种相等性判断逻辑和传统的 == 运算不同,== 运算符会对它两边的操作数做隐式类型转换(如果它们类型不同),然后才进行相等性比较,(所以才会有类似 “” == false 为 true 的现象),但 Object.is不会做这种类型转换。这与
===运算符也不一样。=运算符(和运算符)将数字值-0和+0视为相等,并认为 Number.NaN 不等于 NaN。
实现深拷贝
let obj = {a:'星期一',b:"星期二",c:"星期三",d:"星期四"}
let obj1 = JSON.parse(JSON.stringify(obj))
obj1.a="星期日"
console.log(obj)
console.log(obj1)
console.log(obj == obj1)
Object.fromEntries( ) 将数组转化为对象
const nestedArray = [
['key1', 'value1'],
['key2', 'value2']
]
let obj = Object.fromEntries(nestedArray);
console.log(obj)
// { key 1: "value 1", key 2: "value 2"}
解析URL地址
var paramsString = "q=URLUtils.searchParams&topic=api"
var searchParams = new URLSearchParams(paramsString);
const value = Object.fromEntries(searchParams)
console.log(value)
// {q: "URLUtils.searchParams", topic: "api"}
方法2
const url = 'http://sample.com/?a=1&b=2&c=xx&d#hash'
function setUrl(url){
const data = url.split('?').pop().split('#').shift().split('&');
const res = {};
data.forEach(item => {
const [key, val] = item.split('=');
res[key] = val;
if(!res[key]){
res[key]=""
}
});
return res;
}
console.log(setUrl(url))