gpt4 book ai didi

javascript - 为什么 console.log 在本应只记录一次时记录了不止一次

转载 作者:行者123 更新时间:2023-11-29 19:23:09 24 4
gpt4 key购买 nike

我正在通读 Ari Lerner 的 AngularJS 完整书籍,我在那里找到了 this example在ng级。我在 generateNumber() 函数中添加了一个额外的 console.log。我看到它只记录了一次。

之后,我用 generateNumber() 函数调用替换了使用 x 的地方。更改后我的代码看起来像这样 see this :

HTML

<!doctype html>
<html ng-app="myApp">
<head>
<link rel="stylesheet" href="//cdn.jsdelivr.net/foundation/4.3.2/css/foundation.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0-rc.2/angular.js"></script>
</head>
<body>

<div ng-controller="LotteryController">
<div ng-class="{red: generateNumber() > 5}">
You won!
</div>
<button ng-click="generateNumber()">Draw Number</button>
<p>Number is: {{ x }}</p>
</div>

</body>
</html>

JS

angular.module('myApp', [])
.controller('LotteryController', function($scope) {
$scope.generateNumber = function() {
var num = Math.floor((Math.random()*10)+1);
console.log("Number: "+num);
$scope.x = num;
return num;
};
});

所以我无法理解为什么 console.log() 被记录了那么多次,甚至当我单击按钮时它应该只记录一次但它被记录了不止一次。我不明白为什么多次调用该方法。有时我也会遇到这个异常(我只粘贴了前两行)

Error: [$rootScope:infdig] 10 $digest() iterations reached. Aborting!
Watchers fired in the last 5 iterations:

这个$digest是做什么用的?以及为什么它达到了极限。什么是守望者?并请说明为什么要进行那么多次日志记录?谢谢大家,

编辑

感谢大家的回复,但我想使用类似 ng-class="{red: generateNumber() > 5}" 这样的做法有什么问题。有人可以向我解释一下吗?我不想在那里使用 $scope.x,所以你们现在可以忽略它。

谢谢大家

最佳答案

根据doc :

Processes all of the watchers of the current scope and its children. Because a watcher's listener can change the model, the $digest() keeps calling the watchers until no more listeners are firing. This means that it is possible to get into an infinite loop. This function will throw 'Maximum iteration limit exceeded.' if the number of iterations exceeds 10.

换句话说,$digest 是您的 View 与 $scope 同步的过程。 digest 开始后,它会循环直到 $scope 的状态与其在刚刚过去的循环中的状态相比没有改变。

作用域状态的变化是通过评估 watch 表达式(显式定义或隐含在您的 View 中)来确定的。如果每个表达式在连续循环中的计算结果相同,则摘要将结束。

为了具体解决您的观察,generateNumber() 总是返回一个新数字!因此,$digest 进程总是看到作用域的状态在每个周期结束时发生变化。经过 10 个循环后,系统猜测它处于无限循环中,因此它抛出了您观察到的异常(并且如文档中指定的那样)。

您可以按照以下方法解决问题:

$scope.generateNumber = function () {
$scope.x = Math.floor((Math.random() * 10) + 1);
console.log("Number: " + $scope.x);
};

接下来应对您的标记进行以下更改:

  <div ng-class="{red: x > 5}">
You won!
</div>

正如我读到的,您在其中一条评论中说“我不想直接使用 x”;那么创建一个返回类映射对象的方法就足够了,或者直接将类映射对象添加到范围,或者添加一个将生成的数字返回到范围的方法。

1。添加一个将生成的数字返回到范围的方法

JS:

var number;
$scope.getNumber = function () {
return number;
};
$scope.generateNumber = function () {
$scope.x = Math.floor((Math.random() * 10) + 1);
number = $scope.x;
console.log("Number: " + $scope.x);
};

HTML

  <div ng-class="getNumber() > 5">
You won!
</div>

2。使用返回类映射对象的方法

JS:

var classMap = {};
$scope.getClassMap = function () {
classMap.red = $scope.x > 5;
return classMap;
};

HTML

  <div ng-class="getClassMap()">
You won!
</div>

3。直接将类映射对象添加到作用域

JS:

$scope.classMap = {};
$scope.generateNumber = function () {
$scope.x = Math.floor((Math.random() * 10) + 1);
$scope.classMap.red = $scope.x > 5;
console.log("Number: " + $scope.x);
};

HTML

  <div ng-class="classMap">
You won!
</div>

关于javascript - 为什么 console.log 在本应只记录一次时记录了不止一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32183916/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com