前端常用JS操作与js特性理解——《前端那些事》

简介: 工作中经常用的方法 速记备用

01、 取出两个数组相同的值、不同值

相同值

let arr1 =[1,3,5,7,9];
let arr2 = [1,2,3,4,5,6,7];
let arr3 = arr1.filter(item => arr2 .indexOf(item) > -1) ; // [1, 3, 5, 7]

不同值

let arr1 =[1,3,5,7,9];
let arr2 = [1,2,3,4,5,6,7];
function getArrDifference(arr1, arr2) {
    return arr1.concat(arr2).filter(function(item, i, arr) {
        return arr.indexOf(item) === arr.lastIndexOf(item);
   });
}
let arr3 =getArrDifference(arr1,arr12);  // [9, 2, 4, 6]

02、 数组交集/并集/差集

let a = [1, 2, 3]
let b = [2, 4, 5]

// 并集
let union = a.concat(b.filter((v) => !a.includes(v)))
// [1,2,3,4,5]

// 交集
let intersection = a.filter((v) => b.includes(v))
// [2]

// 差集
let difference = a.concat(b).filter((v) => !a.includes(v) || !b.includes(v))
// [1,3,4,5]

03、判断数据类型


Object.prototype.toString.call()

04、 时间戳转时间 yyyy-mm-dd hh:mm:ss

function getyyyyMMdd(data){
    var d = new Date(data*1000);
    var curr_date = d.getDate();
    var curr_month = d.getMonth() + 1;
    var curr_year = d.getFullYear();
    var curr_hour = d.getHours();;
    var curr_minute = d.getMinutes();
    var curr_second = d.getSeconds();
    String(curr_month).length < 2 ? (curr_month = "0" + curr_month): curr_month;
    String(curr_date).length < 2 ? (curr_date = "0" + curr_date): curr_date;
    String(curr_hour).length < 2 ? (curr_hour = "0" + curr_hour): curr_hour;
    String(curr_minute).length < 2 ? (curr_minute = "0" + curr_minute): curr_minute;
    String(curr_second).length < 2 ? (curr_second = "0" + curr_second): curr_second;
    yyyyMMdd = curr_year + "-" + curr_month +"-"+ curr_date+"  "+curr_hour+":"+curr_minute+":"+curr_second;
   return yyyyMMdd;
}

05、 获取近7天时间

const arr=[] 
for (let i = 0; i < 7; i++) {
        const time = new Date(new Date().setDate(new Date().getDate() + i - 7));
        const year = time.getFullYear();
        const month = `0${time.getMonth() + 1}`.slice(-2);
        const strDate = `0${time.getDate()}`.slice(-2);
        arr.push(`${year}-${month}-${strDate}`);
   }

06、 整数变量交换

1

let a = 10;
let b = 50;
a = a ^ b;
b = a ^ b;
a = a ^ b;
console.log(a, b); // 50 10

2

var a = 2;
var b = 4;
a = a + b;
b = a - b;
a = a - b;
console.log(a, b); // 4 2

3

let a = 10;
let b = 50;
[a,b]=[b,a]
console.log(a);// 50
console.log(b)// 10

07、 数组去重多重方式

  1. Set(最常用)
Array.prototype.unique = function() {
    return [...new Set(this)];
}
var array = [1, 2, 3, 43, 45, 1, 2, 2, 4, 5];
array.unique(); //[1, 2, 3, 43, 45, 4, 5]

2. Map

Array.prototype.unique = function() {
    const tmp = new Map();
    return this.filter(item => {
        return !tmp.has(item) && tmp.set(item, 1);
    })
}
var array = [1, 2, 3, 43, 45, 1, 2, 2, 4, 5];
array.unique(); //[1, 2, 3, 43, 45, 4, 5]

3. Array.prototype.indexOf()

Array.prototype.unique = function() {
    return this.filter((item, index) => {
        return this.indexOf(item) === index;
    })
}
var array = [1, 2, 3, 43, 45, 1, 2, 2, 4, 5];
array.unique(); //[1, 2, 3, 43, 45, 4, 5]

4.Array.prototype.includes()

Array.prototype.unique = function() {
    const newArray = [];
    this.forEach(item => {
        if (!newArray.includes(item)) {
            newArray.push(item);
        }
    });
    return newArray;
}
var array = [1, 2, 3, 43, 45, 1, 2, 2, 4, 5];
array.unique(); //[1, 2, 3, 43, 45, 4, 5]

5. Array.prototype.reduce()

Array.prototype.unique = function() {
    return this.sort().reduce((init, current) => {
        if (init.length === 0 || init[init.length - 1] !== current) {
            init.push(current);
        }
        return init;
    }, []);
}
var array = [1, 2, 3, 43, 45, 1, 2, 2, 4, 5];
array.unique(); //[1, 2, 3, 43, 45, 4, 5]

08、 判断小数是否相等

console.log(0.1 + 0.2  === 0.3); // false

function equal(number1, number2) {
    return Math.abs(number1 - number2) < Math.pow(2, -52);
}
console.log(equal(0.1 + 0.2, 0.3)); //true

09、 多维数组降维度

二维数组

let arr = [ [1], [2], [3] ];
arr = Array.prototype.concat.apply([], arr);
console.log(arr);// [1, 2, 3]

let array = [ [1], [2], [3] ];
array = array.flat(2);  //es6 新增
console.log(array); // [1, 2, 3]

多维数组

1. 调用ES6中的flat方法

let arrMore = [1, 2, [3], [[4]]];
arr= arrMore.flat(Infinity);  //使用 Infinity 作为深度,展开任意深度的嵌套数组
console.log(arr); // [1,2,3,4]

2. replace + split

let arrMore = [1, 2, [3], [[4]]];
let str = JSON.stringify(arrMore);
arr= str.replace(/(\[|\])/g, '').split(',');

3. replace + JSON.parse

let arrMore = [1, 2, [3], [[4]]];
let str = JSON.stringify(arrMore);
str = str.replace(/(\[|\]))/g, '');
str = '[' + str + ']';
arr= JSON.parse(str);

4. 普通递归

let ary= [1, 2, [3], [[4]]];
let result = [];
let fn = function(ary) {
  for(let i = 0; i < ary.length; i++) {
    let item = ary[i];
    if (Array.isArray(ary[i])){
      fn(item);
    } else {
      result.push(item);
    }
  }
}

5. 利用reduce函数迭代

function flatten(ary) {
    return ary.reduce((pre, cur) => {
        return pre.concat(Array.isArray(cur) ? flatten(cur) : cur);
    }, []);
}
let ary= [1, 2, [3], [[4]]];
console.log(flatten(ary))

6. 扩展运算符

//只要有一个元素有数组,那么循环继续
while (ary.some(Array.isArray())) {
  ary = [].concat(...ary);
}

010、 快速浮点数转整数

console.log(10.9 | 0);  // 10
console.log(-10.9 | 0);// 10

console.log(~~10.9); // 10
console.log(~~-10.9); // 10

11、 函数防抖 函数节流

函数防抖:在 n 秒内重新触发,会重新开始计算时间
实现:通过 setTimeout 和 clearTimeout 实现
应用场景:按钮点击事件/input事件,防止用户多次重复提交

//简易写法
let timeout;
$(".xx").click(function() {
    clearTimeout(timeout)    
    timeout = setTimeout(() => {
        //在此处写调用的方法,可以实现仅最后一次操作生效
  }, 1000)
    
})


function debounce (fn, time) {
  let timer = null
  // 闭包
  return () => {
    // 每次都会重新开始计算时间
    clearTimeout(timer)
    timer = setTimeout(() => {
      fn()
    }, time)
  }
}

function sayDebounce() {
  console.log('我是防抖,每次触发我都会重新计算一次时间')
}

btn.onclick = debounce(sayDebounce, 1000);
//或$("#btn").on('click', debounce(confirmExchange, 1000))





函数节流:在 n 秒中只执行一次
实现:通过 setTimeout 执行
应用场景:
- 鼠标/触摸屏的mouseover/touchmove事件
- 页面窗口的resize事件
- 滚动条的scroll事件

// 初步实现
const throttle = function (fn, time) {
  let canRun = true
  // 闭包
  return () => {
    if (canRun) {
      canRun = false
      setTimeout(() => {
        canRun = true
        fn()
      }, time)
    }
  }
}

function sayThrottle() {
  console.log('我是节流,我在固定的时间内执行一次')
}
window.onscroll = throttle(sayThrottle, 1000)

区别:一定时间内任务执行的次数。比如一个事件每1s触发很多次,平均每10ms触发一次。节流,假设时间间隔为100ms,在100ms内只能执行一次事件回调函数,1s内函数的调用次数为:1000 /100 = 10次防抖,假设时间间隔为100ms,时间触发的间隔必须要大于100ms,才调用回调函数。因为触发间隔=10ms < 100ms,1s内函数的调用次数为:0;

12、 按需置顶数组元素

//置顶数组中flag为1的元素
let data = [
        { id: 1, flag: 0 },
        { id: 2, flag: 0 },
        { id: 3, flag: 0 },
        { id: 4, flag: 1 },
        { id: 5, flag: 0 },
        { id: 6, flag: 0 }
      ];
      data.map((item, index) => {
        if (item.flag == 1) {
         data.unshift(data.splice(index, 1)[0]);
        }
      });
      console.log(data);

13、闭包理解

闭包是指有权访问另一个函数作用域中的变量的函数,个人认为闭包最大的用处就是防止对全局作用域的污染。 试想如果我们把一些仅仅只用到一两次的变量都声明在全局作用域中,最后肯定是容易出错且不可维护的。而闭包最神奇的地方就是能在一个函数外访问函数中的局部变量,把这些变量用闭包的形式放在函数中便能避免污染。
一、闭包是什么?
《JavaScript高级程序设计》中写道:“闭包是指有权访问另一个函数作用域中的变量的函数”,如果用下定义的观点看,这句话就是说“闭包是函数”,我带着怀疑的心态又去网上找了找,发现什么说法都有,终究没能明白闭包的含义,还是看代码来得直接。

function outter()

{

var sky="blue";

function inner()

{console.log(sky); 

 }

return inner;}

var result=outter();

result();//"blue"

这段代码就包含一个简单的闭包:outter函数的返回值是一个函数,即inner。inner在outter内部,理所当然能访问到局部变量sky,但当inner作为outter的返回值赋给outter外的全局变量时,神奇的事情发生了:在全局作用域中访问到了sky,这就是闭包。

二、闭包的原理?


每个函数都有自己的执行环境,当一个函数被执行时,它的执行环境就会被推入环境栈,其活动对象(存储环境中定义的变量及函数)加入作用域链中,一旦函数执行完,栈将其环境弹出,活动对象被销毁。·

对于上面的例子来说,outter执行完之后将返回inner给了result,outter的执行环境从环境栈弹出,控制权交给全局环境,outter的活动对象理应被销毁。但此时inner已经存储在全局活动对象中了,同时inner需要访问sky,所以outter的活动对象没有被销毁,即使result执行完毕,outter的活动对象依然存在于作用域链中,只有当result被销毁

result= null;

outter的活动对象才会彻底释放。

三、闭包有什么用?
说了这么多,闭包到底有什么用呢?我个人认为闭包最大的用处就是防止对全局作用域的污染。 试想如果我们把一些仅仅只用到一两次的变量都声明在全局作用域中,最后肯定是容易出错且不可维护的。而闭包最神奇的地方就是能在一个函数外访问函数中的局部变量,把这些变量用闭包的形式放在函数中便能避免污染。
目录
相关文章
|
21天前
|
前端开发 JavaScript 网络协议
前端最常见的JS面试题大全
【4月更文挑战第3天】前端最常见的JS面试题大全
43 5
|
1月前
|
JavaScript 前端开发
JavaScript操作DOM元素
JavaScript操作DOM元素
12 1
|
1月前
|
JavaScript 前端开发 Java
纯前端JS实现人脸识别眨眨眼张张嘴案例
纯前端JS实现人脸识别眨眨眼张张嘴案例
50 0
|
4天前
|
JavaScript 前端开发 UED
深入解析JavaScript原生操作DOM技术
【4月更文挑战第22天】本文深入探讨JavaScript原生DOM操作技术,包括使用`getElement*`方法和CSS选择器获取元素,借助`createElement`与`appendChild`动态创建及插入元素,修改元素内容、属性和样式,以及删除元素。通过掌握这些技术,开发者能实现页面动态交互,但应注意避免过度操作DOM以优化性能和用户体验。
|
4天前
|
JavaScript 前端开发 Linux
JavaScript 的跨平台特性
【4月更文挑战第22天】JavaScript 的跨平台特性
19 8
|
9天前
|
存储 前端开发 API
IndexedDB的异步操作特性对于前端开发者来说有什么挑战和注意事项吗?
IndexedDB是浏览器的客户端数据库,用于前端数据存储。其异步操作特性带来挑战,要求开发者熟悉异步编程,处理回调函数或Promise。注意事务管理,合理控制事务生命周期,防止阻塞。数据版本管理是关键,需处理升级和兼容性问题。错误处理必不可少,确保程序稳定性。性能优化涉及索引设计和查询优化,避免影响应用性能。理解并应对这些挑战,能有效利用IndexedDB构建高效Web应用。
|
11天前
|
存储 JavaScript 前端开发
JavaScript DOM 操作:解释一下 cookie、sessionStorage 和 localStorage 的区别。
Cookie是服务器发送至客户端的文本信息,会随每个请求发送回服务器,适合控制会话状态但可能暴露隐私。SessionStorage仅在当前会话中存储数据,关闭浏览器后清除,适合临时存储如登录状态。LocalStorage则持久保存数据,即使关闭浏览器也不会清除,适用于存储长期设置。三种方式各有侧重,应按需求选择。
15 0
|
11天前
|
JavaScript 前端开发 安全
JavaScript DOM 操作:解释一下浏览器的同源策略。
**同源策略**是浏览器安全基石,它阻止脚本跨不同协议、域名或端口访问资源,防止恶意行为。例如,HTTP页面无法直接用JS获取HTTPS页面内容。**CORS**允许跨域请求,但需服务器配合设置,通过`document.domain`属性可配置,但仍受限于服务器配置。
14 4
|
18天前
|
JavaScript
【归总】原生js操作浏览器hash、url参数参数获取/修改方法合集
【归总】原生js操作浏览器hash、url参数参数获取/修改方法合集
|
24天前
|
人工智能 前端开发 JavaScript
【前端设计】HTML+CSS+JavaScript基本特性
【前端设计】HTML+CSS+JavaScript基本特性