AngularJS中的未定义或空值

80
当我编写观察处理函数时,我会检查undefinednull的newVal参数。为什么AngularJS有这样的行为,但没有特定的实用方法呢?所以有angular.isUndefined但没有angular.isUndefinedOrNull。手动实现不难,但如何扩展angular使每个控制器都拥有该功能呢?谢谢。
$scope.$watch("model", function(newVal) {
    if (angular.isUndefined(newVal) || newVal == null) return;
    // do somethings with newVal
}

处理方式是否是常见的被接受的做法?

编辑2:

JSFiddle示例(http://jsfiddle.net/ubA9r/):

<div ng-app="App">
  <div ng-controller="MainCtrl"> 
      <select ng-model="model" ng-options="m for m in models">
          <option value="" class="ng-binding">Choose model</option>
      </select>
      {{model}}
  </div>
</div>

var app = angular.module("App", []);

var MainCtrl = function($scope) {
    $scope.models = ['Apple', 'Banana'];
    $scope.$watch("model", function(newVal) {
        console.log(newVal);
    });
};

1
你可以换用Coffeescript。它有一个问号后缀运算符可以实现这个功能。 - Patryk Ziemkowski
请问您能否提供一个实际案例,说明何时需要使用这种功能? - Stepan Suvorov
3
为什么不放弃对未定义的检查,只检查 newVal == null - David Sherret
3
如果newVal是undefined,那么(newVal === null)会返回false。 - Greg Dougherty
是的,newVal === null 将会是 false,但是 newVal == null 将会是 true。David 是正确的。 - Patrick McElhaney
6个回答

161

您始终可以将其精确地添加到您的应用程序中

angular.isUndefinedOrNull = function(val) {
    return angular.isUndefined(val) || val === null 
}

我知道这样扩展js库并不总是好的,但它看起来非常接近我的搜索。实际上,我更感兴趣的是为什么我会卡在这里。在监视处理程序中处理未定义和null是标准做法吗? - slo2ols
在我看来,在良好结构的应用程序中不应该出现这种情况。 - Stepan Suvorov
明白了,谢谢。但我仍然认为“null”是正确选择的结果,应该与“undefined”区分开来。 - Stepan Suvorov
24
@STEVER,为什么在良好结构的应用程序中使用“null”会有问题?例如,当用户登录时应该只填充变量的用户数据,在登录之前和注销之后,使用null是正确的值。 - RonLugge

17

我的建议是你自己编写一个实用程序服务。你可以将该服务包含在每个控制器中,或创建一个父控制器,将实用程序服务分配到你的作用域中,然后每个子控制器都将继承此服务,而无需��包含它。

例如:http://plnkr.co/edit/NI7V9cLkQmEtWO36CPXy?p=preview

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope, Utils) {
    $scope.utils = Utils;
});

app.controller('ChildCtrl', function($scope, Utils) {
   $scope.undefined1 = Utils.isUndefinedOrNull(1);  // standard DI
   $scope.undefined2 = $scope.utils.isUndefinedOrNull(1);  // MainCtrl is parent

});

app.factory('Utils', function() {
  var service = {
     isUndefinedOrNull: function(obj) {
         return !angular.isDefined(obj) || obj===null;
     }

  }

  return service;
});

或者您也可以将其添加到rootScope中。这只是一些扩展Angular使用自己的实用函数的选项。


4
我坚信效用函数不应该使用依赖注入。 - slo2ols
@slo2ols 要封装它,您可以创建一个服务并仅将其注入到根中。 - lucuma

14

我之前向 lodash 的维护者们提出了同样的问题, 他们回答说可以使用 != 运算符:

if(newVal != null) {
  // newVal is defined
}

这里使用JavaScript的类型转换来检查值是否为undefinednull

如果您正在使用JSHint来检查代码规范,可以添加以下注释块告诉它您知道自己在做什么 - 大多数情况下被认为是不好的!=运算符。

/* jshint -W116 */ 
if(newVal != null) {
/* jshint +W116 */
  // newVal is defined
}

9
为什么不直接使用否定形式的angular.isObject?例如:
if (!angular.isObject(obj)) {
    return;
}

...但如果您知道值的类型并且可以选择与之匹配的 angular.isX 方法,则是一个很好的选择。 - Phasmal
null 是一个对象。 - spicykimchi
isObject 文档中:返回值:如果 value 是一个 Object 但不是 null,则为 True。 - DerMike

7
@STEVER的回答已经令人满意。不过,我认为发表一个略有不同的方法可能会有用。我使用了一种叫做isValue的方法,它返回除null、undefined、NaN和Infinity之外的所有值都为true。将NaN与null和undefined归为一类是该函数对我来说真正的好处。将Infinity与null和undefined归为一类更具争议性,但实际上对我的代码没有太大兴趣,因为我几乎从不使用Infinity。
以下代码受Y.Lang.isValue启发。这是Y.Lang.isValue的源代码
/**
 * A convenience method for detecting a legitimate non-null value.
 * Returns false for null/undefined/NaN/Infinity, true for other values,
 * including 0/false/''
 * @method isValue
 * @static
 * @param o The item to test.
 * @return {boolean} true if it is not null/undefined/NaN || false.
 */
angular.isValue = function(val) {
  return !(val === null || !angular.isDefined(val) || (angular.isNumber(val) && !isFinite(val)));
};

作为工厂的一部分
.factory('lang', function () {
  return {
    /**
     * A convenience method for detecting a legitimate non-null value.
     * Returns false for null/undefined/NaN/Infinity, true for other values,
     * including 0/false/''
     * @method isValue
     * @static
     * @param o The item to test.
     * @return {boolean} true if it is not null/undefined/NaN || false.
     */
    isValue: function(val) {
      return !(val === null || !angular.isDefined(val) || (angular.isNumber(val) && !isFinite(val)));
  };
})

为什么不用 val === null || !angular.isDefined(val) 直接替换成 val == null - J.Steve

3

lodash 提供了一种简便的方法来检查变量是否为 undefined 或 null:_.isNil(yourVariable)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接