快速搜索对象属性的不必要突变的来源

你好 今天,我将告诉您如何使用调试器解决非平凡的JavaScript问题。

在JavaScript中,对象是一种复合数据类型;其值通过引用传递。 换句话说,当我们将一个对象作为参数传递给函数时,或在任何可以更改其属性的地方。 使用由存储链接的变量表达式以及点和赋值运算符组成的指令。 之后,其他适用于或将与此变量/参数一起使用的指令将通过引用获得属性更改。

通常,此行为会使用户数据失真,导致错误并且是不希望的。

寻找这种不想要的属性更改的源可能要花费很长时间:因此该程序可能已经很大,并且包含成千上万的指令。

让我们看一个简单的例子。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Debug property mutation example</title> <script> const user = { firstName: 'Vasilij', middleName: 'Alibabaevich', lastName: 'Radner', aka: 'Alibaba', getFullName() { return `${this.lastName} ${this.firstName.slice(0, 1)}. ${this.middleName.slice(0, 1)}.` } }; </script> <script src="object-property-mutation.js" type="application/javascript"></script> </head> </head> <body> <script> Promise.resolve(user).then(user.getFullName.bind(user)).then(console.log); </script> </body> </html> 

现在,Web程序不起作用,因为控制台中有错误,并且没有名称输出

图片

我们在控制台中阅读了最上面的消息:

 Uncaught (in promise) TypeError: Cannot read property 'slice' of undefined 

像这样的错误:未处理(作为承诺):我无法从未定义中读取slice属性。

单击链接,然后转到错误的位置。

 getFullName() { return `${this.lastName} ${this.firstName.slice(0, 1)}. ${this.middleName.slice(0, 1)}.` } 

我们看到错误的表达
 this.firstName.slice(0, 1) 
由四个运算符组成:

  1. 两个点运算符
  2. 一个逗号分隔符
  3. 一个分组运算符-一对括号

让我们阅读说明。 左表达式首先被求值

 this.firstName 

它由一个点运算符组成,其左侧为基本运算符,右侧为标识符firstName。 该表达式的结果将是不确定的。 执行以下dot语句将导致错误。 由于点运算符仅适用于对象类型,因此从未定义执行将导致错误-我无法从未定义获取slice属性。

事实证明,此属性在某处设置为undefined ...

要解决此问题,让我们尝试相反的做法。 我们将使用调试工具停止异常 。 从错误的位置向下移至调用堆栈,我们尝试移至更改属性的指令。

选择异常停止工具


图片

我们看到堆栈中只有两个调用。 转到上一个电话。

图片

我们看到没有显式指令更改firstName属性。

图片

我们得出结论,此调用堆栈中不会发生更改。

你觉得怎么样


以及如何找到更改了我的对象的属性的反派?

请在评论中写下您如何找到它?
和我一起工作的人以及我告诉过您的人,请在评论中写一个星号。

我非常想知道其他JavaScript专家如何解决此类问题。

您知道,当我第一次遇到这种JavaScript行为时,我花了几个小时研究并撕下刘海中的一簇头发……

在异常情况下禁用暂停工具。

因此,这是我们的新计划,我们将使用getter和setter在用户对象中定义firstName属性。

我们使用debugger语句和分号语句将debug语句添加到setter中。

 const user = { _firstName: 'Vasilij', set firstName(value) { debugger; this._firstName = value; }, get firstName() {return this._firstName}, middleName: 'Alibabaevich', lastName: 'Radner', aka: 'Alibaba', getFullName() { return `${this.lastName} ${this.firstName.slice(0, 1)}. ${this.middleName.slice(0, 1)}.`; } }; 

沿着调用堆栈进一步移动,我们发现了一条更改firstName属性的指令。

在将新值写入对象之前,调试器在设置器中停止。

图片

我们看到参数值的值是不确定的。

现在,使用调用堆栈,我们可以轻松地转到上一个调用。

图片

iiiii,胜利aaaaaah。

有一种使用调试工具在异常停止时解决此问题的方法,甚至更简单。

这是我们的新计划:我们将使用户对象不是对象,并且使用异常停止工具可以轻松地获得错误的指令。

因为我们知道,尝试从未定义的属性获取属性时会发生错误。

我们打开异常停止工具,将用户变量设置为undefined。

  const user = undefined; 

我们再次在firstName属性变形的地方停了下来。

图片

这就是我今天要告诉您的有关调试对象上不需要的更改的全部信息。

感谢您阅读本文。 喜欢,订阅频道,与好友分享这段视频和文章,尽力而为。

github.com/NVBespalov/js-lessons/tree/error/property-mutation

Source: https://habr.com/ru/post/zh-CN481824/


All Articles