开发者

How to convert anything to a String safely in JavaScript

开发者 https://www.devze.com 2023-01-27 18:29 出处:网络
If I have: var test = {toString: function(){alert(\"evil code\"); return \"test\";}}; how can I convert test to a string? without calling test.toString() and without using a typeof x == \"string\"

If I have:

var test = {toString: function(){alert("evil code"); return "test";}};

how can I convert test to a string? without calling test.toString() and without using a typeof x == "string" c开发者_JS百科heck since I want to allow non strings.

Note: this is for a FF extension dealing with objects from a content page's js scope.


Sadly, @Matthew Flaschen's (currently accepted) answer does not work with the Symbol class from ES6 / ES2015:

console.log("" + Symbol("foo"));
// results in an exception: 
//   `Uncaught TypeError: Cannot convert a Symbol value to a string` 
// (at least in Chrome as of this writing).

https://jsfiddle.net/L8adq9y4/

(I have no idea why, as Symbol has a perfectly good toString() method:)

console.log(Symbol("foo").toString());

https://jsfiddle.net/v1rqfhru/

There's a solution though: the String() function seems to be able to convert any value (at least out of the ones I tried) into a String. It will even call toString() if it exists:

console.log(String("A String"));
console.log(String(undefined));
console.log(String(null));
console.log(String({value: "An arbitrary object"}));
console.log(String({toString: function(){return "An object with a toString() method";}}));
console.log(String(function(){return "An arbitrary function"}));

https://jsfiddle.net/6uc83tsc/

So, pass anything you like into String() and you'll get a pretty good result.


JavaScript allows you to modify the properties of pretty much any object that is accessible to your script, including Object.prototype itself, meaning any object is vulnerable to "evil code" in the manner that you explained.

Only primitives are guaranteed to be safe, so the only way to ensure that "evil code" is never executed is to do something like this:

function safeToString(x) {
  switch (typeof x) {
    case 'object':
      return 'object';
    case 'function':
      return 'function';
    default:
      return x + '';
  }
}


One option is:

Object.prototype.toString.call(test)

This gives:

"[object Object]"

in the case of test. Basically, it just gives type information. However, I wonder what the exact scenario is here. How is the evil object getting loaded into the page? If they can execute arbitrary code on the page, you're basically out of luck. Among other things, it is then possible to redefine Object.prototype.toString.


Your (toString: function(){alert("evil code"); return "test";}) doesn't even get parsed here, it throws a syntax error. I think you wanted to use {} instead of ().

Normally you could use an empty string and the plus operator to perform a cast:

""+test;
""+2; // "2"
""+4.5 // "4.5"
""+[1, 2, 3] // "1,2,3"
""+{} // '[object Object]'

But here, there's no real way to convert the object safely.

You can use delete test.toString to get rid of the overridden method, after that it will fall back to the normal toString method which returns '[object Object]'. You can also convert the toString method itself into a string via test.toString.toString().

"function () { alert("evil code"); return "test"; }"

It's up to you what you exactly want to do here.


You can check only undefined cases and convert it to using String constructor like this.

let a = [1,2,3]

String(a)

Exceptional case : String(undefined) --> "undefined"

Hope it helps


You can use lodash toString method.

_.toString(null);
// => ''

_.toString(-0);
// => '-0'

_.toString([1, 2, 3]);
// => '1,2,3'

Link to documentation

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号