Skip to content

Commit c98f534

Browse files
PatrickJSpetebacondarwin
authored andcommitted
refactor(*): introduce isNumberNaN
window.isNaN(‘lol’); //=> true Number.isNaN(‘lol’); //=> false isNaN converts it’s arguments into a Number before checking if it’s NaN. In various places in the code base, we are checking if a variable is a Number and NaN (or not), so this can be simplified with this new method (which is not exported on the global Angular object). Closes angular#11242
1 parent 1844b8e commit c98f534

File tree

10 files changed

+16
-57
lines changed

10 files changed

+16
-57
lines changed

src/.eslintrc.json

+1
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"isObject": false,
4646
"isString": false,
4747
"isNumber": false,
48+
"isNumberNaN": false,
4849
"isDate": false,
4950
"isArray": false,
5051
"isFunction": false,

src/Angular.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
isBlankObject,
4141
isString,
4242
isNumber,
43+
isNumberNaN,
4344
isDate,
4445
isArray,
4546
isFunction,
@@ -413,6 +414,11 @@ function toInt(str) {
413414
return parseInt(str, 10);
414415
}
415416

417+
var isNumberNaN = Number.isNaN || function isNumberNaN(num) {
418+
// eslint-disable-next-line no-self-compare
419+
return num !== num;
420+
};
421+
416422

417423
function inherit(parent, extra) {
418424
return extend(Object.create(parent), extra);
@@ -1277,7 +1283,7 @@ function timezoneToOffset(timezone, fallback) {
12771283
// IE/Edge do not "understand" colon (`:`) in timezone
12781284
timezone = timezone.replace(ALL_COLONS, '');
12791285
var requestedTimezoneOffset = Date.parse('Jan 01, 1970 00:00:00 ' + timezone) / 60000;
1280-
return isNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
1286+
return isNumberNaN(requestedTimezoneOffset) ? fallback : requestedTimezoneOffset;
12811287
}
12821288

12831289

src/ng/directive/input.js

-47
Original file line numberDiff line numberDiff line change
@@ -1543,53 +1543,6 @@ function parseNumberAttrVal(val) {
15431543
return !isNumberNaN(val) ? val : undefined;
15441544
}
15451545

1546-
function isNumberInteger(num) {
1547-
// See http://stackoverflow.com/questions/14636536/how-to-check-if-a-variable-is-an-integer-in-javascript#14794066
1548-
// (minus the assumption that `num` is a number)
1549-
1550-
// eslint-disable-next-line no-bitwise
1551-
return (num | 0) === num;
1552-
}
1553-
1554-
function countDecimals(num) {
1555-
var numString = num.toString();
1556-
var decimalSymbolIndex = numString.indexOf('.');
1557-
1558-
if (decimalSymbolIndex === -1) {
1559-
if (-1 < num && num < 1) {
1560-
// It may be in the exponential notation format (`1e-X`)
1561-
var match = /e-(\d+)$/.exec(numString);
1562-
1563-
if (match) {
1564-
return Number(match[1]);
1565-
}
1566-
}
1567-
1568-
return 0;
1569-
}
1570-
1571-
return numString.length - decimalSymbolIndex - 1;
1572-
}
1573-
1574-
function isValidForStep(viewValue, stepBase, step) {
1575-
// At this point `stepBase` and `step` are expected to be non-NaN values
1576-
// and `viewValue` is expected to be a valid stringified number.
1577-
var value = Number(viewValue);
1578-
1579-
// Due to limitations in Floating Point Arithmetic (e.g. `0.3 - 0.2 !== 0.1` or
1580-
// `0.5 % 0.1 !== 0`), we need to convert all numbers to integers.
1581-
if (!isNumberInteger(value) || !isNumberInteger(stepBase) || !isNumberInteger(step)) {
1582-
var decimalCount = Math.max(countDecimals(value), countDecimals(stepBase), countDecimals(step));
1583-
var multiplier = Math.pow(10, decimalCount);
1584-
1585-
value = value * multiplier;
1586-
stepBase = stepBase * multiplier;
1587-
step = step * multiplier;
1588-
}
1589-
1590-
return (value - stepBase) % step === 0;
1591-
}
1592-
15931546
function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) {
15941547
badInputChecker(scope, element, attr, ctrl);
15951548
baseInputType(scope, element, attr, ctrl, $sniffer, $browser);

src/ng/directive/ngModel.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
548548
*/
549549
this.$validate = function() {
550550
// ignore $validate before model is initialized
551-
if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
551+
if (isNumberNaN(ctrl.$modelValue)) {
552552
return;
553553
}
554554

@@ -719,7 +719,7 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
719719
}
720720
}
721721
}
722-
if (isNumber(ctrl.$modelValue) && isNaN(ctrl.$modelValue)) {
722+
if (isNumberNaN(ctrl.$modelValue)) {
723723
// ctrl.$modelValue has not been touched yet...
724724
ctrl.$modelValue = ngModelGet($scope);
725725
}

src/ng/directive/ngPluralize.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
206206

207207
scope.$watch(numberExp, function ngPluralizeWatchAction(newVal) {
208208
var count = parseFloat(newVal);
209-
var countIsNaN = isNaN(count);
209+
var countIsNaN = isNumberNaN(count);
210210

211211
if (!countIsNaN && !(count in whens)) {
212212
// If an explicit number rule such as 1, 2, 3... is defined, just use it.
@@ -216,7 +216,7 @@ var ngPluralizeDirective = ['$locale', '$interpolate', '$log', function($locale,
216216

217217
// If both `count` and `lastCount` are NaN, we don't need to re-register a watch.
218218
// In JS `NaN !== NaN`, so we have to explicitly check.
219-
if ((count !== lastCount) && !(countIsNaN && isNumber(lastCount) && isNaN(lastCount))) {
219+
if ((count !== lastCount) && !(countIsNaN && isNumberNaN(lastCount))) {
220220
watchRemover();
221221
var whenExpFn = whensExpFns[count];
222222
if (isUndefined(whenExpFn)) {

src/ng/directive/validators.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ var maxlengthDirective = function() {
259259
var maxlength = -1;
260260
attr.$observe('maxlength', function(value) {
261261
var intVal = toInt(value);
262-
maxlength = isNaN(intVal) ? -1 : intVal;
262+
maxlength = isNumberNaN(intVal) ? -1 : intVal;
263263
ctrl.$validate();
264264
});
265265
ctrl.$validators.maxlength = function(modelValue, viewValue) {

src/ng/filter/limitTo.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ function limitToFilter() {
106106
} else {
107107
limit = toInt(limit);
108108
}
109-
if (isNaN(limit)) return input;
109+
if (isNumberNaN(limit)) return input;
110110

111111
if (isNumber(input)) input = input.toString();
112112
if (!isArrayLike(input)) return input;

src/ng/rootScope.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -806,8 +806,7 @@ function $RootScopeProvider() {
806806
if ((value = get(current)) !== (last = watch.last) &&
807807
!(watch.eq
808808
? equals(value, last)
809-
: (typeof value === 'number' && typeof last === 'number'
810-
&& isNaN(value) && isNaN(last)))) {
809+
: (isNumberNaN(value) && isNumberNaN(last)))) {
811810
dirty = true;
812811
lastDirtyWatch = watch;
813812
watch.last = watch.eq ? copy(value, null) : value;

test/.eslintrc.json

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
"isObject": false,
6060
"isString": false,
6161
"isNumber": false,
62+
"isNumberNaN": false,
6263
"isDate": false,
6364
"isArray": false,
6465
"isFunction": false,

test/ng/directive/selectSpec.js

-1
Original file line numberDiff line numberDiff line change
@@ -1223,6 +1223,5 @@ describe('select', function() {
12231223
'</select>');
12241224
}).toThrowMinErr('ng','badname', 'hasOwnProperty is not a valid "option value" name');
12251225
});
1226-
12271226
});
12281227
});

0 commit comments

Comments
 (0)