返回顶部
首页 > 资讯 > 精选 >JavaScript怎么监测数组的变化
  • 655
分享到

JavaScript怎么监测数组的变化

2023-06-20 16:06:58 655人浏览 泡泡鱼
摘要

这篇文章主要讲解了“javascript怎么监测数组的变化”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript怎么监测数组的变化”吧!前言之前介绍defineProperty的

这篇文章主要讲解了“javascript怎么监测数组的变化”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript怎么监测数组的变化”吧!

前言

之前介绍defineProperty的时候说到,其只能监测对象的变化,并不能监测数组的变化。

本文致力于说清楚怎么实现监测数组的变化。

核心思路:找到改变原数组的方法,然后对这些方法进行劫持处理。

上面这句话,是重中之重,务必读三遍,记住了,再往下走。

改变原数组,常用到的方法有push pop shift unshift reverse sort splice。

换言之,这些方法是改变数组的入口。

在数组实例和数组原型之间,加一个新的原型

直接修改Array.prototype,是极其危险的。

换一个思路,复制已有的数组原型,然后修改其中的方法,但这里因为原型上的方法不可枚举,自然也就没法复制。

于是再换一个思路,在数组和数组的原型之间,插入一个原型,形成原型链,数组 => 新原型 => 数组的原型,可以在新原型上增加同名的方法就可以了。

先借助伪代码理解:

// 伪代码let arr = [];arr.__proto__ = newPrototype;newPrototype.__proto__ = Array.prototype;// 然后可以在新原型上添加同名的方法就可以了newPrototype.push = xxx;

转换成真实的代码如下,核心使用了Object.create,

// Object.create返回一个新对象,而来新对象的__proto__就是传进去的参数。let newPrototype = Object.create(Array.prototype);// 然后可以在新原型上添加同名的方法就可以了newPrototype.push = xxx;// 需要监测的数组,绑定新的原型就可以了let arr = [];arr.__proto__ = newPrototype;

以 push 为例,劫持 push

就是在新原型上重新写一个 push 的方法,里面执行老的 push,但除此之外还可以做点别的事。

let newPrototype = Object.create(Array.prototype);// 在新原型上添加同名pushnewPrototype.push = function(...args) {  // 语义化this  let curArr = this;  console.log("使用了push");  // 最后还是会执行原始的push  return Array.prototype.push.call(curArr, ...args);};// 需要监测的数组,绑定新的原型就可以了let arr = [];arr.__proto__ = newPrototype;// 执行push的时候,就会打印了arr.push(1);

然后其他的方法也是类似的,试着写写其他的方法

劫持其他的方法

将其他方法也一起写了,因为逻辑一样,直接遍历即可。

let newPrototype = Object.create(Array.prototype);let methods = ["push", "pop", "shift", "unshift", "reverse", "sort", "splice"];methods.forEach(method => {  newPrototype[method] = function(...args) {    console.log(`使用了${method}`);    return Array.prototype[method].call(this, ...args);  };});// 需要监测的数组,绑定新的原型就可以了let arr = [];arr.__proto__ = newPrototype;// 执行的时候,就会打印了arr.push(1);arr.pop();

数组里有数组项的话,也是需要监测的

这里数组里可能也是有数组的,需要遍历数组的每项,如果是数组的话依然需要指向新的原型。

嗯,对,用到递归了。

let newPrototype = Object.create(Array.prototype);let methods = ["push", "pop", "shift", "unshift", "reverse", "sort", "splice"];methods.forEach(method => {  newPrototype[method] = function(...args) {    console.log(`使用了${method}`);    return Array.prototype[method].call(this, ...args);  };});function observeArr(arr) {  // 既是条件限制,也是递归的终止条件  if (!Array.isArray(arr)) {    return;  }  // 整个数组指向新的原型  arr.__proto__ = newPrototype;  // 数组的每项,如果是数组,也指向新的原型。  arr.forEach(observeArr);}// 需要监测的数组,绑定新的原型就可以了let arr = [[1, 2, 3]];observeArr(arr);// 执行的时候,就会打印了arr[0].push(1);arr[1].pop();

数组新添加的项,如果是数组也需要指向新的原型

能添加元素的方法:push unshift splice。

找到新加的元素,然后是数组的也同样指向新的原型

let newPrototype = Object.create(Array.prototype);let methods = ["push", "pop", "shift", "unshift", "reverse", "sort", "splice"];methods.forEach(method => {  newPrototype[method] = function(...args) {    console.log(`使用了${method}`);    let inserted;    switch (method) {      case "push":      case "unshift":        inserted = args;        break;      case "splice":        inserted = args.slice(2);        break;      default:        break;    }    inserted && observeArr(inserted);    return Array.prototype[method].call(this, ...args);  };});function observeArr(arr) {  // 即是条件限制,也是递归的终止条件  if (!Array.isArray(arr)) {    return;  }  // 整个数组指向新的原型  arr.__proto__ = newPrototype;  // 数组的每项,如果是数组,也指向新的原型。  arr.forEach(observeArr);}// 这里可以导出去,方便别的文件使用export default observeArr;// 需要监测的数组,绑定新的原型就可以了let arr = [];observeArr(arr);let addItem = [1, 2, 3];arr.push(addItem);// 执行的时候,就会打印了addItem.push(1);addItem.pop();

综合使用 defineProperty 监测对象和数组

现在已经有了监测对象的方法,也有了监测数组的方法,将两个综合起来,就能监测数组里面的对象,对象里面的数组了。

将监测数组和监测对象的的可以单独写成一个文件,方便之后使用。

这里为了方便直接运行代码,直接放在一块了。

// 生成新的原型let newPrototype = Object.create(Array.prototype);let methods = ["push", "pop", "shift", "unshift", "reverse", "sort", "splice"];// 在新原型上面添加以上方法,实现劫持methods.forEach(method => {  newPrototype[method] = function(...args) {    console.log(`使用了${method}`);    let inserted;    switch (method) {      case "push":      case "unshift":        inserted = args;        break;      case "splice":        inserted = args.slice(2);        break;      default:        break;    }    inserted && observeArr(inserted);    return Array.prototype[method].call(this, ...args);  };});function observeArr(arr) {  // 新加!!!是对象的话,需要用对象  if (Object.prototype.toString.call(arr) === "[object Object]") {    observeObj(arr);    return;  }  if (Array.isArray(arr)) {    // 整个数组指向新的原型    arr.__proto__ = newPrototype;    // 数组的每项,如果是数组,也指向新的原型。    arr.forEach(observeArr);  }  // 不是对象或者数组的,什么都不做}function observeObj(obj) {  // 加上参数限制,必须是对象才有劫持,也是递归的终止条件  if (typeof obj !== "object" || obj == null) {    return;  }  // 新加!!!数组交给数组处理  if (Array.isArray(obj)) {    observeArr(obj);    return;  }  // 是对象的话 才开始递归  for (let key in obj) {    // 直接使用 obj.hasOwnProperty会提示不规范    if (Object.prototype.hasOwnProperty.call(obj, key)) {      observeKey(obj, key);      // 这里劫持该属性的属性值,如果不是对象直接返回,不影响      observeObj(obj[key]);    }  }  return obj;}function observeKey(obj, key) {  let value = obj[key];  Object.defineProperty(obj, key, {    get() {      console.log("读取属性", value);      return value;    },    set(newValue) {      console.log("设置属性", newValue);      value = newValue;    }  });}let data = { a: 1, b: [1, 2, { c: 2 }] };observeObj(data);data.a = 2;data.b.push([2, 3]);let arr = [{ a: "数组里的对象" }, 3, 4];observeArr(arr);arr[0].a = 3;

缺陷

当然数组其实可以不通过方法改变,比如直接删除数组可以直接使用 length 属性,或者直接arr[0]=xxx改变数组。

但只有当使用"push","pop", "shift","unshift","reverse","sort","splice"才能检测到数组变化。

这也是 Vue 的缺陷,当然新版的 proxy 将干掉这个缺陷。

所以在使用 vue 的过程中,要尽量使用以上方法操作数组~~~

附注:查看数组的所有属性和方法

在控制台可以输入dir([]),然后能看到数组所有的属性和方法。

具体用法,可以直接到到mdn 上细看,点击侧边栏看对应的方法

JavaScript怎么监测数组的变化

感谢各位的阅读,以上就是“JavaScript怎么监测数组的变化”的内容了,经过本文的学习后,相信大家对JavaScript怎么监测数组的变化这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

--结束END--

本文标题: JavaScript怎么监测数组的变化

本文链接: https://lsjlt.com/news/298341.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • JavaScript怎么监测数组的变化
    这篇文章主要讲解了“JavaScript怎么监测数组的变化”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript怎么监测数组的变化”吧!前言之前介绍defineProperty的...
    99+
    2023-06-20
  • JavaScript如何监测数组的变化
    前言 之前介绍defineProperty的时候说到,其只能监测对象的变化,并不能监测数组的变化。 本文致力于说清楚怎么实现监测数组的变化。 核心思路:找到改变原数组的方法,然后对这...
    99+
    2024-04-02
  • 详解Vue如何监测数组的变化
    目录一、使用 Vue.js 提供的方法来更新数组二、使用专门用于监测数组变化的语法糖三、使用Vue.observable()函数四、使用 computed 属性和 watch 属性监...
    99+
    2023-01-28
    Vue监测数组变化 Vue 数组变化 Vue 数组
  • vue中怎么监听数组变化
    这篇文章主要介绍了vue中怎么监听数组变化,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。vue是什么Vue是一套用于构建用户界面的渐进式JavaScript框架,Vue与其它...
    99+
    2023-06-14
  • vuex 中怎么利用state监听数组变化
    这期内容当中小编将会给大家带来有关vuex 中怎么利用state监听数组变化,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。import Vue fro...
    99+
    2024-04-02
  • Android怎么监测文件夹内容变化
    本篇内容主要讲解“Android怎么监测文件夹内容变化”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android怎么监测文件夹内容变化”吧!一. 概述:android.os包下的FileObs...
    99+
    2023-06-25
  • angular怎么监听数据变化
    在Angular中,可以使用Angular的Change Detection机制来监听数据的变化。 使用双向数据绑定:双向数据绑...
    99+
    2023-10-24
    angular
  • mysql怎么监听数据变化
    MySQL本身并没有提供直接监听数据变化的功能。但是可以通过以下几种方式来实现数据变化的监听: 使用触发器(Trigger):可...
    99+
    2024-04-09
    mysql
  • vuex如何用state监听数组变化
    这篇文章主要介绍了vuex如何用state监听数组变化的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇vuex如何用state监听数组变化文章都会有所收获,下面我们一起来看看吧。代码如下:import ...
    99+
    2023-07-04
  • vue中是如何检测数组变化的
    vue中检测数组变化的方法:vue使用函数劫持的方式,通过重写数组的某些方法来检测数组变化。在将数组处理成响应式数据后,如果使用数组原始方法改变数组时,数组值会发生变化,但是并不会触发数组的setter来通知所有依赖该数组的地方进行更新,若...
    99+
    2024-04-02
  • C#实现数据库数据变化监测(sqlserver&mysql)
    监测数据库表数据变化,可实现数据库同步(一主一从(双机备份),一主多从(总部数据库,工厂1,工厂2,工厂数据合并到总部数据)) sqlserver 启用数据库监听服务 ALTER DATABASE test SET NEW_BROKER W...
    99+
    2023-09-22
    数据库 sqlserver mysql
  • java怎么监听oracle数据变化
    要监听Oracle数据库中的数据变化,可以使用Oracle的触发器(Trigger)或者Oracle的Java消息服务(Oracle...
    99+
    2023-10-27
    java oracle
  • python怎么监听数据库表的变化
    在Python中,可以使用数据库的触发器(trigger)来监听数据库表的变化。触发器是一段在特定事件(例如插入、更新、删除等)发生...
    99+
    2023-09-09
    python 数据库
  • 关于vue中如何监听数组变化
    目录前言源码部分从哪开始第一步学习呢从图开始看看源码吧前言 前段时间学习了关于vue中响应式数据的原理,(并作了学习笔记vue响应式原理),其实是通过Object.definePro...
    99+
    2024-04-02
  • 怎么监测和优化OLAP数据库
    这篇文章的内容主要围绕怎么监测和优化OLAP数据库进行讲述,文章内容清晰易懂,条理清晰,非常适合新手学习,值得大家去阅读。感兴趣的朋友可以跟随小编一起阅读吧。希望大家通过这篇文章有所收获!优化在线分析处理的...
    99+
    2024-04-02
  • vue如何检测对象和数组的变化
    这篇文章主要介绍了vue如何检测对象和数组的变化的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇vue如何检测对象和数组的变化文章都会有所收获,下面我们一起来看看吧。检测对象变化1、不能检测到对象属性的添加或删除...
    99+
    2023-07-04
  • 怎么使用Shell脚本实现监测文件变化
    这篇文章主要讲解了“怎么使用Shell脚本实现监测文件变化”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用Shell脚本实现监测文件变化”吧!代码完整的shell脚本如下,可以直接使用...
    99+
    2023-07-02
  • java怎么实时监控数据变化
    在Java中实现实时监控数据变化的方式主要有以下几种:1. 使用线程轮询:创建一个线程,在循环中定期地查询数据的变化情况。可以使用`...
    99+
    2023-08-17
    java
  • Vue子组件监听父组件值的变化
    目录子组件监听父组件值变化子组件监听父组件的值同步更新数据子组件监听父组件值变化 子组件中利用watch监听父组件值的变化 // 子组件 props: ["a"],     watc...
    99+
    2024-04-02
  • 怎么通过Java监听MySQL数据的变化
    这篇文章主要介绍“怎么通过Java监听MySQL数据的变化”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“怎么通过Java监听MySQL数据的变化”文章能帮助大家解决问题。原理:java通过bin-l...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作