简体   繁体   中英

Extending js prototype, argument is getting type coerced

I have a function that start's like this:

Object.prototype.search=function(str){
  var o=this;
  var keys=Object.keys(o);
  var obj={};
  str=str.toLowerCase();
  var regEx=new RegExp(str,"ig");
  ... etc.

Note - this is just a quick and dirty function for searching through some data. I'm sure what I want could be achieved more effectively, but I just wanted to understand something, etc..

I created the rest of the function, and on my first try in the console, I happened to pass it a number. Now the number is passed as a string, and I want it to be a string, and when I run "555".toLowerCase() in the console, no problem, returns string unchanged as expected. However, when I try and execute the function, it throws an exception:

uncaught TypeError: str.toLowerCase is not a function
at Number.Object.search

So I can see that it's converting my string into a number, but I can't understand why. Is it because I'm working on a built-in object? The error is thrown on the line where I attempt str=str.toLowerCase() . Seems like the solution would be to explicitly declare it as a string, but I can see why I need to.

Any ideas?

Edit: Here is my code - I know it's yucky, but now I'm having other issues, and I'm just curious, because I can't figure out what's going on:

Object.prototype.search=function(str){
  const o=this;
  var keys=Object.keys(o);
  var values=Object.values(o);
  var obj={};
  var regex=new RegExp(str.toLowerCase(),"ig");
  values=values.map((value,index)=>{
    if(value){
      value=value.toString();
      return value.search(regex) !==-1 ? index : false;
    } 
      return false;
   }).filter(e=>!!e);

   values.forEach((e,i)=>{
     var key=keys[i];
     var value=o[key]; 
     obj[key]=value;
  });
  return obj;
  };

Edit: And here is it in action:

var x={"cat":"23","hat":"45"};
x.search("2");

Expected result:  {"cat":"23"};

Not: After I included the null check for value, I'm no longer getting an error, but I'm also not getting the results I'd expect. In other words, I'm getting an object back, and it's filtered, but it's returning the "wrong" values given the argument passed.

Edit: Okay - it is now fixed. The problem was in this line: var key=keys[i]; . I was using the index of the keys instead of the index of the values. So now its right. But I still can't understand why I was getting the error I was prior to the null check. I'll close this if people think I should, but I still don't understand why I was getting the error.

Cleaner version of your function:

 Object.defineProperty(Object.prototype, 'search', { value: function(regex) { let found = {}; for (let k in this) { if (this.hasOwnProperty(k) && regex.test(this[k].toString())) found[k] = this[k]; } return found; }, enumerable: false }); console.log(({ cat: 23, hat: 45 }).search(/2/)); console.log(({ cat: 23, hat: 45 }).search(/.*/)); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM