Indefinido o nulo para AngularJS

80

Cuando escribo funciones de manejo de relojes, verifico el parámetro newVal en undefinedy null. ¿Por qué AngularJS tiene tal comportamiento, pero no tiene un método de utilidad particular? Entonces hay angular.isUndefinedpero no angular.isUndefinedOrNull. No es difícil implementar eso a mano, pero ¿cómo extender el angular para tener esa función en cada controlador? Tnx.

Editar :

El ejemplo:

$scope.$watch("model", function(newVal) {
    if (angular.isUndefined(newVal) || newVal == null) return;
    // do somethings with newVal
}

¿Es una práctica común y aceptada manejar de esa manera?

Edición 2 :

El ejemplo de 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);
    });
};
slo2ols
fuente
1
Puede cambiar a coffeescript. Hay un operador postifix de signo de interrogación que hace eso.
Patryk Ziemkowski
¿Podría dar el caso real cuando necesite dicha funcionalidad?
Stepan Suvorov
3
¿Por qué no perder el cheque indefinido y simplemente verificar newVal == null?
David Sherret
3
Porque (newVal === null) devuelve falso si newVal no está definido.
Greg Dougherty
Sí, newVal === nullserá falso, pero newVal == nullserá cierto. David tiene razón.
Patrick McElhaney

Respuestas:

160

Siempre puede agregarlo exactamente para su aplicación

angular.isUndefinedOrNull = function(val) {
    return angular.isUndefined(val) || val === null 
}
Stepan Suvorov
fuente
Sé que no siempre es bueno extender las bibliotecas js de esa manera, pero se parece mucho a mi búsqueda. En realidad, me interesa más por qué me quedé atrapado. ¿Es una práctica estándar manejar undefined y null en los manejadores de relojes?
slo2ols
Bueno, en mi humilde opinión, en una aplicación bien estructurada no debería haber tales casos.
Stepan Suvorov
lo tengo, gracias. Pero sigo pensando que 'nulo' es el resultado de una selección correcta y debería distinguirse de 'indefinido'.
Stepan Suvorov
24
@STEVER ¿por qué 'null' sería malo en una aplicación bien estructurada? Si, por ejemplo, una variable solo debe llenarse con datos de usuario cuando el usuario está conectado, null es el valor adecuado antes de iniciar sesión y después de cerrar la sesión.
RonLugge
17

Mi sugerencia es que escriba su propio servicio público. Puede incluir el servicio en cada controlador o crear un controlador principal, asignar el servicio de utilidad a su alcance y luego cada controlador secundario heredará esto sin que usted tenga que incluirlo.

Ejemplo: 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;
});

O también puede agregarlo a rootScope. Solo algunas opciones para extender angular con sus propias funciones de utilidad.

lúcuma
fuente
4
Creo firmemente que las funciones de utilidad no deberían ser DI
slo2ols
@ slo2ols para encapsularlo, puede crear un servicio e inyectarlo solo en el roo
lucuma
14

Hice la misma pregunta a los mantenedores de lodash hace un tiempo y respondieron mencionando que el !=operador se puede usar aquí:

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

Esto usa la coerción de tipo de JavaScript para verificar el valor de undefinedo null.

Si está utilizando JSHint para filtrar su código, agregue los siguientes bloques de comentarios para decirle que sabe lo que está haciendo; la mayoría de las veces !=se considera malo.

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

¿Por qué no usarlo simplemente angular.isObjectcon negación? p.ej

if (!angular.isObject(obj)) {
    return;
}
Pete
fuente
... pero es una gran opción si sabe de qué tipo es el valor y puede elegir un angular.isXmétodo para hacer coincidir.
Phasmal
nulles un objeto
spicykimchi
Del isObjectdocumento: Devuelve: True si valuees un Objectpero no null.
DerMike
7

La respuesta de @ STEVER es satisfactoria. Sin embargo, pensé que podría ser útil publicar un enfoque ligeramente diferente. Utilizo un método llamado isValue que devuelve verdadero para todos los valores excepto null, undefined, NaN e Infinity. Agrupar en NaN con nulo e indefinido es el beneficio real de la función para mí. Agrupar Infinity con nulo e indefinido es más discutible, pero francamente no es tan interesante para mi código porque prácticamente nunca uso Infinity.

El siguiente código está inspirado en Y.Lang.isValue . Aquí está la fuente de 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)));
};

O como parte de una fábrica

.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)));
  };
})
Steven Wexler
fuente
¿Por qué no reemplazar val === null || !angular.isDefined(val)con solo val == null?
J.Steve
3

lodash proporciona un método abreviado para verificar si no está definido o es nulo: _.isNil(yourVariable)

nigong
fuente