Skip to content

Commit edfaa66

Browse files
committedSep 1, 2016
Fix 'has' not handling deep null/undefined values (#73)
1 parent e75f78b commit edfaa66

File tree

2 files changed

+32
-14
lines changed

2 files changed

+32
-14
lines changed
 

‎index.js

+14-12
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@
1414
})(this, function(){
1515
'use strict';
1616

17-
var
18-
toStr = Object.prototype.toString,
19-
_hasOwnProperty = Object.prototype.hasOwnProperty;
17+
var toStr = Object.prototype.toString;
18+
function hasOwnProperty(obj, prop) {
19+
if(obj == null) {
20+
return false
21+
}
22+
//to handle objects with null prototypes (too edge case?)
23+
return Object.prototype.hasOwnProperty.call(obj, prop)
24+
}
2025

2126
function isEmpty(value){
2227
if (!value) {
@@ -26,7 +31,7 @@
2631
return true;
2732
} else if (typeof value !== 'string') {
2833
for (var i in value) {
29-
if (_hasOwnProperty.call(value, i)) {
34+
if (hasOwnProperty(value, i)) {
3035
return false;
3136
}
3237
}
@@ -79,7 +84,7 @@
7984
};
8085

8186
function getShallowProperty(obj, prop) {
82-
if (options.includeInheritedProps || (typeof prop === 'number' && Array.isArray(obj)) || _hasOwnProperty.call(obj, prop)) {
87+
if (options.includeInheritedProps || (typeof prop === 'number' && Array.isArray(obj)) || hasOwnProperty(obj, prop)) {
8388
return obj[prop];
8489
}
8590
}
@@ -116,24 +121,21 @@
116121
}
117122

118123
objectPath.has = function (obj, path) {
119-
if (obj == null) {
120-
return false;
121-
}
122-
123124
if (typeof path === 'number') {
124125
path = [path];
125126
} else if (typeof path === 'string') {
126127
path = path.split('.');
127128
}
128129

129130
if (!path || path.length === 0) {
130-
return false;
131+
return !!obj;
131132
}
132133

133134
for (var i = 0; i < path.length; i++) {
134135
var j = getKey(path[i]);
136+
135137
if((typeof j === 'number' && isArray(obj) && j < obj.length) ||
136-
(options.includeInheritedProps ? (j in Object(obj)) : _hasOwnProperty.call(obj, j))) {
138+
(options.includeInheritedProps ? (j in Object(obj)) : hasOwnProperty(obj, j))) {
137139
obj = obj[j];
138140
} else {
139141
return false;
@@ -184,7 +186,7 @@
184186
value.length = 0;
185187
} else if (isObject(value)) {
186188
for (i in value) {
187-
if (_hasOwnProperty.call(value, i)) {
189+
if (hasOwnProperty(value, i)) {
188190
delete value[i];
189191
}
190192
}

‎test.js

+18-2
Original file line numberDiff line numberDiff line change
@@ -550,11 +550,16 @@ describe('has', function () {
550550
expect(objectPath.has({}, 'a')).to.be.equal(false);
551551
});
552552

553-
it('should return false for empty path', function () {
553+
it('should handle empty paths properly', function () {
554554
var obj = getTestObj();
555555
expect(objectPath.has(obj, '')).to.be.equal(false);
556-
expect(objectPath.has(obj, [])).to.be.equal(false);
557556
expect(objectPath.has(obj, [''])).to.be.equal(false);
557+
obj[''] = 1
558+
expect(objectPath.has(obj, '')).to.be.equal(true);
559+
expect(objectPath.has(obj, [''])).to.be.equal(true);
560+
561+
expect(objectPath.has(obj, [])).to.be.equal(true);
562+
expect(objectPath.has(null, [])).to.be.equal(false);
558563
});
559564

560565
it('should test under shallow object', function() {
@@ -614,6 +619,17 @@ describe('has', function () {
614619
obj.key = undefined;
615620
expect(objectPath.has(obj, 'key')).to.be.equal(true);
616621
});
622+
623+
it('should work with deep undefined/null values', function() {
624+
var obj = {};
625+
expect(objectPath.has(obj, 'missing.test')).to.be.equal(false);
626+
627+
obj.missing = null;
628+
expect(objectPath.has(obj, 'missing.test')).to.be.equal(false);
629+
630+
obj.sparseArray = [1, undefined, 3]
631+
expect(objectPath.has(obj, 'sparseArray.1.test')).to.be.equal(false);
632+
});
617633
});
618634

619635

0 commit comments

Comments
 (0)
Please sign in to comment.