1

我一直在关注 John Papa 和他的 Angular 风格指南建议。我喜欢将所有可用于视图的变量和方法放在控制器顶部并依靠 javascript 在运行时提升变量的想法。我显然不像我想象的那样理解提升。在下面的示例中,我希望将dumbValue 变量声明提升到$scope.dumbValue 赋值语句之上;

var app = angular.module('plunker', []);
app.controller('MainCtrl', [$scope, $http]);
function MainCtrl($scope,$http)
{
    $scope.dumbValue = dumbValue;
    var dumbValue = 'dumb';
}

但是在这个 Plunker中,您可以看到情况并非如此。选择 ng-model 值未初始化。如果将赋值语句移到变量声明下,则初始化 ng-model。

为什么 javascript 不提升var dumbValue上面的分配,或者它是关于 Angular 处理它的方式我不理解的东西?

4

2 回答 2

4

您必须将我链接到 Papa 为我提出此建议的位置,但我只看到Papa 建议为“可绑定成员”执行此操作。他在谈论函数——而不是标量值。您正在尝试执行后者,这样做会遇到问题。

你看,提升将变量的声明移动到作用域的顶部,而不是它们的定义(又名assignments)。如果您在一个语句中声明和定义,则提升将其分成两个语句并提升前者。

所以这段代码:

var MainCtrl = function ($scope,$http) {
    $scope.dumbValue = dumbValue;

    var dumbValue = 'dumb';
}

与编写此代码相同(因为提升将其变为此):

var MainCtrl = function ($scope,$http) {
    var dumbValue; // declared, not defined (hence the value `undefined`)

    $scope.dumbValue = dumbValue; // assignment of `undefined` to a property of $scope

    dumbValue = 'dumb'; // definition of your variable with a string value
}

然而,正如我所说,Papa 正在谈论将绑定到$scope. 他说而不是这样做:

var MainCtrl = function ($scope,$http) {
    function foo () {};

    $scope.foo = foo;
}

做这个:

var MainCtrl = function ($scope,$http) {
    $scope.foo = foo;

    function foo () {};
}

这是有效的,因为提升将命名函数语句转换为将新变量定义为函数的变量声明,然后将它们拆分为两个单独的语句并将它们放在顶部。因此,Papa 推荐的版本(最后一个代码块)通过提升转换为:

var MainCtrl = function ($scope,$http) {
    var foo;

    foo = function () {};

    $scope.foo = foo;
}

如您所见,这种对命名函数语句的不同处理允许foo在绑定到$scope发生之前将其定义为函数。

Personally, I don't like Papa's recommendation here. Although I personally understand hoisting and don't get bit by it, I have seen many developers create issues by writing code which gets changed in hoisting. This being the case, I am very particular to write my code exactly as the hoist would have converted it in order to avoid having my code misunderstood by the majority of developers. This is the way JSLint's default settings would have you write it as well.

于 2014-10-08T16:37:49.457 回答
1

When you do this ...

var app = angular.module('plunker', []);
app.controller('MainCtrl', [$scope, $http]);
function MainCtrl($scope,$http)
{
    $scope.dumbValue = dumbValue;
    var dumbValue = 'dumb';
}

this is actually what is happening.

var app = angular.module('plunker', []);
app.controller('MainCtrl', [$scope, $http]);
function MainCtrl($scope,$http)
{
    var dumbValue = undefined;
    $scope.dumbValue = dumbValue;
    dumbValue = 'dumb';
}

So the variable is hoisted, but is set to undefined. Then later it gets its value, but too late in this case. This is why hoisting of variables is not recommended. Always put those up top.

于 2014-10-12T03:41:18.927 回答