前端常用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的活动对象才会彻底释放。

三、闭包有什么用?
说了这么多,闭包到底有什么用呢?我个人认为闭包最大的用处就是防止对全局作用域的污染。 试想如果我们把一些仅仅只用到一两次的变量都声明在全局作用域中,最后肯定是容易出错且不可维护的。而闭包最神奇的地方就是能在一个函数外访问函数中的局部变量,把这些变量用闭包的形式放在函数中便能避免污染。
目录
相关文章
|
2月前
|
JavaScript 前端开发 程序员
前端原生Js批量修改页面元素属性的2个方法
原生 Js 的 getElementsByClassName 和 querySelectorAll 都能获取批量的页面元素,但是它们之间有些细微的差别,稍不注意,就很容易弄错!
|
2月前
|
JavaScript 前端开发 Java
springboot解决js前端跨域问题,javascript跨域问题解决
本文介绍了如何在Spring Boot项目中编写Filter过滤器以处理跨域问题,并通过一个示例展示了使用JavaScript进行跨域请求的方法。首先,在Spring Boot应用中添加一个实现了`Filter`接口的类,设置响应头允许所有来源的跨域请求。接着,通过一个简单的HTML页面和jQuery发送AJAX请求到指定URL,验证跨域请求是否成功。文中还提供了请求成功的响应数据样例及请求效果截图。
springboot解决js前端跨域问题,javascript跨域问题解决
|
2月前
|
JavaScript 前端开发 安全
JavaScript与TypeScript的对比,分析了两者的特性及在实际项目中的应用选择
本文深入探讨了JavaScript与TypeScript的对比,分析了两者的特性及在实际项目中的应用选择。JavaScript以其灵活性和广泛的生态支持著称,而TypeScript通过引入静态类型系统,提高了代码的可靠性和可维护性,特别适合大型项目。文章还讨论了结合使用两种语言的优势,以及如何根据项目需求和技术背景做出最佳选择。
64 4
|
2月前
|
缓存 JavaScript 前端开发
JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用
本文深入讲解了 JavaScript 与 DOM 交互的基础及进阶技巧,涵盖 DOM 获取、修改、创建、删除元素的方法,事件处理,性能优化及与其他前端技术的结合,助你构建动态交互的网页应用。
54 5
|
2月前
|
缓存 前端开发 JavaScript
JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式
本文深入解析了JavaScript前端路由的实现原理及其在单页应用中的重要性,涵盖前端路由概念、基本原理、常见实现方式(Hash路由和History路由)、优点及挑战,并通过实际案例分析,帮助开发者更好地理解和应用这一关键技术,提升用户体验。
81 1
|
2月前
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
56 4
|
3月前
|
存储 人工智能 前端开发
前端大模型应用笔记(三):Vue3+Antdv+transformers+本地模型实现浏览器端侧增强搜索
本文介绍了一个纯前端实现的增强列表搜索应用,通过使用Transformer模型,实现了更智能的搜索功能,如使用“番茄”可以搜索到“西红柿”。项目基于Vue3和Ant Design Vue,使用了Xenova的bge-base-zh-v1.5模型。文章详细介绍了从环境搭建、数据准备到具体实现的全过程,并展示了实际效果和待改进点。
207 2
|
3月前
|
JavaScript 前端开发 程序员
前端学习笔记——node.js
前端学习笔记——node.js
58 0
|
3月前
|
人工智能 自然语言处理 运维
前端大模型应用笔记(一):两个指令反过来说大模型就理解不了啦?或许该让第三者插足啦 -通过引入中间LLM预处理用户输入以提高多任务处理能力
本文探讨了在多任务处理场景下,自然语言指令解析的困境及解决方案。通过增加一个LLM解析层,将复杂的指令拆解为多个明确的步骤,明确操作类型与对象识别,处理任务依赖关系,并将自然语言转化为具体的工具命令,从而提高指令解析的准确性和执行效率。
|
3月前
|
存储 弹性计算 算法
前端大模型应用笔记(四):如何在资源受限例如1核和1G内存的端侧或ECS上运行一个合适的向量存储库及如何优化
本文探讨了在资源受限的嵌入式设备(如1核处理器和1GB内存)上实现高效向量存储和检索的方法,旨在支持端侧大模型应用。文章分析了Annoy、HNSWLib、NMSLib、FLANN、VP-Trees和Lshbox等向量存储库的特点与适用场景,推荐Annoy作为多数情况下的首选方案,并提出了数据预处理、索引优化、查询优化等策略以提升性能。通过这些方法,即使在资源受限的环境中也能实现高效的向量检索。