Как безопасно преобразовать что-либо в строку в JavaScript - PullRequest
12 голосов
/ 30 ноября 2010

Если у меня есть:

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

, как я могу преобразовать test в строку?без вызова test.toString() и без использования проверки typeof x == "string", поскольку я хочу разрешить не строки.

Примечание: это для расширения FF, имеющего дело с объектами из области js контентной страницы.

Ответы [ 5 ]

6 голосов
/ 30 ноября 2010

Ваш (toString: function(){alert("evil code"); return "test";}) здесь даже не анализируется, он выдает синтаксическую ошибку.Я думаю, что вы хотели использовать {} вместо ().

Обычно вы могли бы использовать пустую строку и оператор плюс для выполнения приведения:

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

Но здесь нет реального способа безопасного преобразования объекта.

Вы можете использовать delete test.toString, чтобы избавиться от переопределенного метода, после этого он вернется к обычному методу toString, который возвращает'[object Object]'.Вы также можете преобразовать сам метод toString в строку с помощью test.toString.toString().

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

Вам решать, что именно вы хотите здесь делать.

5 голосов
/ 30 ноября 2010

JavaScript позволяет вам изменять свойства практически любого объекта, который доступен вашему сценарию, включая сам Object.prototype, что означает, что любой объект уязвим для «злого кода», как вы объяснили .

Только примитивы гарантированно безопасны, поэтому единственный способ гарантировать, что «злой код» никогда не будет выполнен, это сделать что-то вроде этого:

function safeToString(x) {
  switch (typeof x) {
    case 'object':
      return 'object';
    case 'function':
      return 'function';
    default:
      return x + '';
  }
}
4 голосов
/ 30 ноября 2010

Один из вариантов:

Object.prototype.toString.call(test)

Это дает:

"[object Object]"

в случае теста.По сути, он просто дает информацию о типе.Тем не менее, мне интересно, что точный сценарий здесь.Как злой объект загружается на страницу?Если они могут выполнить произвольный код на странице, вам в основном не повезло.Кроме всего прочего, тогда можно переопределить Object.prototype.toString.

2 голосов
/ 22 октября 2016

К сожалению, ответ @Matthew Flaschen (в настоящее время принятый) не работает с классом Symbol из 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/

(понятия не имеюпочему, поскольку Symbol имеет совершенно хороший метод toString() :)

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

https://jsfiddle.net/v1rqfhru/

Хотя есть решение: функция String(), по-видимому, может преобразовыватьлюбое значение (по крайней мере из тех, которые я пробовал) в String.Он даже вызовет toString(), если он существует:

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/

Итак, передайте все, что вам нравится, в String(), и вы получите довольно хороший результат.

0 голосов
/ 06 октября 2017

Вы можете использовать метод lodash toString.

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

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

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

Ссылка на документацию

...