function typeOf(o) {
  return Object.prototype.toString.call(o).split(' ')[1].split(']')[0].toLowerCase();
}
function isUndefined(o) {
  return typeOf(o) === 'undefined';
}
function where(collection, source) {
  var checkArr = [];
  if (typeOf(collection) === 'object') {
    checkArr = [collection];
  } else if (typeOf(collection) === 'array') {
    checkArr = collection;
  }
  function isObjectSemiSame(obj, source, u) {
    return Object.keys(source).every(function(key) {
      if (isUndefined(obj) || isUndefined(obj[key])) {
        return;
      }
      if (typeOf(source[key]) === 'object' || typeOf(source[key]) === 'array') {
        return isObjectSemiSame(obj[key], source[key]);
      }
      return source[key] === obj[key];
    });
  }
  return checkArr.filter(function(item) {
    return isObjectSemiSame(item, source);
  });
}
describe('where method', function() {
  it('testing with strings', function() {
    var collection = [
      "one",
      "two",
      "three"
    ];
    var collection = [
      "bamboo",
      "two",
      "bamboo",
      "link"
    ];
    expect(where(collection, "two")).toEqual(["two"]);
    expect(where(collection, "bamboo")).toEqual(["bamboo", "bamboo"]);
  });
  it('testing with one object', function() {
    var collection1 = {
      name: 'raju',
      age: 23,
    };
    var collection2 = {
      name: 'Friko',
      age: 36,
    };
    expect(where(collection1, {
      name: 'raju'
    })).toEqual([collection1]);
    expect(where(collection1, {
      name: 'Dump'
    })).toEqual([]);
    expect(where(collection2, {
      age: 36
    })).toEqual([collection2]);
    expect(where(collection2, {
      car: 'audi'
    })).toEqual([]);
  });
  it('testing with one level object', function() {
    var collection = [{
      name: 'jack',
      age: 25
    }, {
      name: 'missi',
      age: 23
    }, {
      name: 'reddy',
      age: 46
    }];
    var source1 = {
      name: 'reddy'
    };
    var source2 = {
      age: 25
    };
    expect(where(collection, source1)).toEqual([collection[2]]);
    expect(where(collection, source2)).toEqual([collection[0]]);
  });
  it('testing with multilevel object', function() {
    var collection = [{
      name: 'jack',
      age: 25,
      level1: {
        name: 'l1',
        level2: {
          name: 'l2',
          level3: {
            name: 'l3'
          }
        }
      }
    }, {
      name: 'missi',
      age: 23,
      level1: {
        name: 'l1'
      }
    }, {
      name: 'reddy',
      age: 46,
      feature: {
        flag: false
      }
    }];
    var source1 = {
      level1: {
        name: 'l1'
      }
    };
    var source2 = {
      level1: {
        name: 'l1',
        level2: {
          name: 'l2'
        }
      }
    };
    var source3 = {
      feature: {
        flag: false
      }
    };
    expect(where(collection, source1).length).toBe(2);
    expect(where(collection, source1)).toEqual(jasmine.arrayContaining([
      collection[0],
      collection[1]
    ]));
    expect(where(collection, source2)).toEqual([collection[0]]);
    expect(where(collection, source3)).toEqual([collection[2]]);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/jasmine-html.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/2.2.1/boot.min.js"></script>
 
source?getOwnPropertyNames()function useful.