HTML-кодировка теряется при чтении атрибута из поля ввода

Я использую JavaScript, чтобы извлечь значение из скрытого поля и отобразить его в текстовом поле. Значение в скрытом поле кодируется.

Например,

<input id='hiddenId' type='hidden' value='chalk &amp; cheese' />

втягивается в

<input type='text' value='chalk &amp; cheese' />

через некоторый jQuery, чтобы получить значение из скрытого поля (именно в этот момент я теряю кодировку):

$('#hiddenId').attr('value')

Проблема в том, что когда я читаю chalk &amp; cheese Из скрытого поля JavaScript, похоже, теряет кодировку. Сбежать " а также 'Я хочу, чтобы кодировка осталась.

Есть ли библиотека JavaScript или метод jQuery, который будет кодировать строку в HTML?

26 ответов

Решение

Я использую эти функции:

function htmlEncode(value){
  // Create a in-memory div, set its inner text (which jQuery automatically encodes)
  // Then grab the encoded contents back out. The div never exists on the page.
  return $('<div/>').text(value).html();
}

function htmlDecode(value){
  return $('<div/>').html(value).text();
}

В основном элемент div создается в памяти, но он никогда не добавляется к документу.

На htmlEncode Функция, которую я установил innerText элемента, и получить закодированный innerHTML; на htmlDecode Функция, которую я установил innerHTML значение элемента и innerText получается

Проверьте работающий пример здесь.

Уловка jQuery не кодирует кавычки, а в IE она лишит вас пробелов.

Основываясь на теге escape- шаблона в Django, который, я думаю, уже интенсивно используется / проверен, я сделал эту функцию, которая делает то, что нужно.

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

function htmlEscape(str) {
    return str
        .replace(/&/g, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');
}

// I needed the opposite function today, so adding here too:
function htmlUnescape(str){
    return str
        .replace(/&quot;/g, '"')
        .replace(/&#39;/g, "'")
        .replace(/&lt;/g, '<')
        .replace(/&gt;/g, '>')
        .replace(/&amp;/g, '&');
}

Обновление 2013-06-17:
В поисках самого быстрого выхода я нашел эту реализацию replaceAll метод:
http://dumpsite.com/forum/index.php?topic=4.msg29
(также упоминается здесь: самый быстрый метод для замены всех вхождений символа в строке)
Некоторые результаты производительности здесь:
http://jsperf.com/htmlencoderegex/25

Это дает идентичную строку результата для встроенного replace цепи выше. Я был бы очень рад, если бы кто-то мог объяснить, почему это быстрее!?

Обновление 2015-03-04:
Я только что заметил, что AngularJS использует именно метод, описанный выше:
https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js#L435

Они добавляют пару уточнений - они, кажется, обрабатывают неясную проблему Unicode, а также преобразуют все не алфавитно-цифровые символы в сущности. У меня сложилось впечатление, что последнее не нужно, если у вас есть кодировка UTF8, указанная для вашего документа.

Отмечу, что (4 года спустя) Джанго все еще не выполняет ни одну из этих вещей, поэтому я не уверен, насколько они важны:
https://github.com/django/django/blob/1.8b1/django/utils/html.py

Обновление 2016-04-06:
Вы также можете избежать косой черты /, Это не требуется для правильного кодирования HTML, однако это рекомендуется OWASP в качестве меры безопасности против XSS. (спасибо @JNF за предложение об этом в комментариях)

        .replace(/\//g, '&#x2F;');

Вот не-jQuery-версия, которая значительно быстрее, чем jQuery. .html() версия и .replace() версия. Это сохраняет все пробелы, но, как и версия jQuery, не обрабатывает кавычки.

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

Скорость: http://jsperf.com/htmlencoderegex/17

тест скорости

Демо - версия: jsFiddle

Выход:

выход

Автор сценария:

function htmlEncode( html ) {
    return document.createElement( 'a' ).appendChild( 
        document.createTextNode( html ) ).parentNode.innerHTML;
};

function htmlDecode( html ) {
    var a = document.createElement( 'a' ); a.innerHTML = html;
    return a.textContent;
};

document.getElementById( 'text' ).value = htmlEncode( document.getElementById( 'hidden' ).value );

//sanity check
var html = '<div>   &amp; hello</div>';
document.getElementById( 'same' ).textContent = 
      'html === htmlDecode( htmlEncode( html ) ): ' 
    + ( html === htmlDecode( htmlEncode( html ) ) );

HTML:

<input id="hidden" type="hidden" value="chalk    &amp; cheese" />
<input id="text" value="" />
<div id="same"></div>

Я знаю, что это старый, но я хотел опубликовать вариант принятого ответа, который будет работать в IE без удаления строк:

function multiLineHtmlEncode(value) {
    var lines = value.split(/\r\n|\r|\n/);
    for (var i = 0; i < lines.length; i++) {
        lines[i] = htmlEncode(lines[i]);
    }
    return lines.join('\r\n');
}

function htmlEncode(value) {
    return $('<div/>').text(value).html();
} 

Подчеркивание обеспечивает _.escape() а также _.unescape() методы, которые делают это.

> _.unescape( "chalk &amp; cheese" );
  "chalk & cheese"

> _.escape( "chalk & cheese" );
  "chalk &amp; cheese"

Для тех, кто предпочитает простой javascript, вот метод, который я успешно использовал:

function escapeHTML (str)
{
    var div = document.createElement('div');
    var text = document.createTextNode(str);
    div.appendChild(text);
    return div.innerHTML;
}

Хороший ответ. Обратите внимание, что если значение для кодирования undefined или же null с jQuery 1.4.2 вы можете получить такие ошибки, как:

jQuery("<div/>").text(value).html is not a function

ИЛИ ЖЕ

Uncaught TypeError: Object has no method 'html'

Решение состоит в том, чтобы изменить функцию, чтобы проверить фактическое значение:

function htmlEncode(value){ 
    if (value) {
        return jQuery('<div/>').text(value).html(); 
    } else {
        return '';
    }
}

Быстрее без Jquery. Вы можете закодировать каждый символ в вашей строке:

function encode(e){return e.replace(/[^]/g,function(e){return"&#"+e.charCodeAt(0)+";"})}

Или просто нацеливайтесь на главных героев, о которых нужно беспокоиться (&, inebreaks, <,>, "и '), например:

function encode(r){
return r.replace(/[\x26\x0A\<>'"]/g,function(r){return"&#"+r.charCodeAt(0)+";"})
}

test.value=encode('Encode HTML entities!\n\n"Safe" escape <script id=\'\'> & useful in <pre> tags!');

testing.innerHTML=test.value;

/*************
* \x26 is &ampersand (it has to be first),
* \x0A is newline,
*************/
<textarea id=test rows="9" cols="55"></textarea>

<div id="testing">www.WHAK.com</div>

FWIW, кодировка не теряется. Кодировка используется анализатором разметки (браузером) во время загрузки страницы. Как только источник прочитан и проанализирован, и браузер загрузил DOM в память, кодировка была проанализирована в том, что он представляет. Таким образом, к тому времени, когда ваш JS выполняется для чтения чего-либо в памяти, символ, который он получает, представляет собой то, что представляет кодировка.

Возможно, я работаю строго над семантикой, но я хотел, чтобы вы поняли цель кодирования. Слово "потерял" звучит так, как будто что-то не работает так, как должно.

Прототип имеет встроенный класс String. Так что, если вы используете / планируете использовать Prototype, он делает что-то вроде:

'<div class="article">This is an article</div>'.escapeHTML();
// -> "&lt;div class="article"&gt;This is an article&lt;/div&gt;"

Вот простое решение JavaScript. Он расширяет объект String методом "HTMLEncode", который можно использовать для объекта без параметра или с параметром.

String.prototype.HTMLEncode = function(str) {
  var result = "";
  var str = (arguments.length===1) ? str : this;
  for(var i=0; i<str.length; i++) {
     var chrcode = str.charCodeAt(i);
     result+=(chrcode>128) ? "&#"+chrcode+";" : str.substr(i,1)
   }
   return result;
}
// TEST
console.log("stetaewteaw æø".HTMLEncode());
console.log("stetaewteaw æø".HTMLEncode("æåøåæå"))

Я сделал суть "метод HTMLEncode для JavaScript".

afaik в javascript нет никаких простых методов HTML Encode/Decode.

Однако, что вы можете сделать, это использовать JS для создания произвольного элемента, установить его внутренний текст, а затем прочитать его с помощью innerHTML.

скажем, с jQuery это должно работать:

var helper = $('chalk & cheese').hide().appendTo('body');
var htmled = helper.html();
helper.remove();

или что-то в этом роде

Моя функция чистого JS:

/**
 * HTML entities encode
 *
 * @param {string} str Input text
 * @return {string} Filtered text
 */
function htmlencode (str){

  var div = document.createElement('div');
  div.appendChild(document.createTextNode(str));
  return div.innerHTML;
}

JavaScript HTML-объекты кодируют и декодируют

Основано на санитарной обработке angular... (синтаксис модуля es6)

// ref: https://github.com/angular/angular.js/blob/v1.3.14/src/ngSanitize/sanitize.js
const SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
const NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g;

const decodeElem = document.createElement('pre');


/**
 * Decodes html encoded text, so that the actual string may
 * be used.
 * @param value
 * @returns {string} decoded text
 */
export function decode(value) {
  if (!value) return '';
  decodeElem.innerHTML = value.replace(/</g, '&lt;');
  return decodeElem.textContent;
}


/**
 * Encodes all potentially dangerous characters, so that the
 * resulting string can be safely inserted into attribute or
 * element text.
 * @param value
 * @returns {string} encoded text
 */
export function encode(value) {
  if (value === null || value === undefined) return '';
  return String(value).
    replace(/&/g, '&amp;').
    replace(SURROGATE_PAIR_REGEXP, value => {
      var hi = value.charCodeAt(0);
      var low = value.charCodeAt(1);
      return '&#' + (((hi - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000) + ';';
    }).
    replace(NON_ALPHANUMERIC_REGEXP, value => {
      return '&#' + value.charCodeAt(0) + ';';
    }).
    replace(/</g, '&lt;').
    replace(/>/g, '&gt;');
}

export default {encode,decode};

Вот немного, что подражает Server.HTMLEncode Функция из ASP Microsoft, написанная на чистом JavaScript:

function htmlEncode(s) {
  var ntable = {
    "&": "amp",
    "<": "lt",
    ">": "gt",
    "\"": "quot"
  };
  s = s.replace(/[&<>"]/g, function(ch) {
    return "&" + ntable[ch] + ";";
  })
  s = s.replace(/[^ -\x7e]/g, function(ch) {
    return "&#" + ch.charCodeAt(0).toString() + ";";
  });
  return s;
}

Результат не кодирует апострофы, но кодирует другие специальные элементы HTML и любые символы вне диапазона 0x20-0x7e.

У меня была похожая проблема, и я решил ее с помощью функции encodeURIComponent из JavaScript ( документация)

Например, в вашем случае, если вы используете:

<input id='hiddenId' type='hidden' value='chalk & cheese' />

а также

encodeURIComponent($('#hiddenId').attr('value'))

ты получишь chalk%20%26%20cheese, Даже места сохранены.

В моем случае мне пришлось закодировать одну обратную косую черту, и этот код работает отлично

encodeURIComponent('name/surname')

и я получил name%2Fsurname

Вам не нужно экранировать / кодировать значения, чтобы перемещать их из одного поля ввода в другое.

<form>
 <input id="button" type="button" value="Click me">
 <input type="hidden" id="hiddenId" name="hiddenId" value="I like cheese">
 <input type="text" id="output" name="output">
</form>
<script>
    $(document).ready(function(e) {
        $('#button').click(function(e) {
            $('#output').val($('#hiddenId').val());
        });
    });
</script>

JS не вставляет необработанный HTML или что-либо еще; он просто говорит DOM, чтобы установить value свойство (или атрибут; не уверен). В любом случае, DOM решает любые проблемы с кодированием для вас. Если вы не делаете что-то странное, как использование document.write или же evalHTML-кодирование будет эффективно прозрачным.

Если вы говорите о создании нового текстового поля для хранения результата... это все еще так же просто. Просто передайте статическую часть HTML в jQuery, а затем установите остальные свойства / атрибуты для объекта, который он возвращает вам.

$box = $('<input type="text" name="whatever">').val($('#hiddenId').val());

Если вы хотите использовать jQuery. Я нашел это:

http://www.jquerysdk.com/api/jQuery.htmlspecialchars

(часть плагина jquery.string, предлагаемого jQuery SDK)

Я считаю, что проблема с прототипом заключается в том, что он расширяет базовые объекты в JavaScript и будет несовместим с любым jQuery, который вы, возможно, использовали. Конечно, если вы уже используете Prototype, а не jQuery, это не будет проблемой.

РЕДАКТИРОВАТЬ: Также есть это, который является портом строковых утилит Prototype для jQuery:

http://stilldesigning.com/dotstring/

Я столкнулся с некоторыми проблемами с обратной косой чертой в строке "Домен \ Пользователь".

Я добавил это к другим побегам от ответа Anentropic

.replace(/\\/g, '&#92;')

Что я нашел здесь: Как избежать обратной косой черты в JavaScript?

var htmlEnDeCode = (function() {
    var charToEntityRegex,
        entityToCharRegex,
        charToEntity,
        entityToChar;

    function resetCharacterEntities() {
        charToEntity = {};
        entityToChar = {};
        // add the default set
        addCharacterEntities({
            '&amp;'     :   '&',
            '&gt;'      :   '>',
            '&lt;'      :   '<',
            '&quot;'    :   '"',
            '&#39;'     :   "'"
        });
    }

    function addCharacterEntities(newEntities) {
        var charKeys = [],
            entityKeys = [],
            key, echar;
        for (key in newEntities) {
            echar = newEntities[key];
            entityToChar[key] = echar;
            charToEntity[echar] = key;
            charKeys.push(echar);
            entityKeys.push(key);
        }
        charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
        entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
    }

    function htmlEncode(value){
        var htmlEncodeReplaceFn = function(match, capture) {
            return charToEntity[capture];
        };

        return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
    }

    function htmlDecode(value) {
        var htmlDecodeReplaceFn = function(match, capture) {
            return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
        };

        return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
    }

    resetCharacterEntities();

    return {
        htmlEncode: htmlEncode,
        htmlDecode: htmlDecode
    };
})();

Это из исходного кода ExtJS.

HtmlEncodes заданное значение

  var htmlEncodeContainer = $('<div />');
  function htmlEncode(value) {
    if (value) {
      return htmlEncodeContainer.text(value).html();
    } else {
      return '';
    }
  }
<script>
String.prototype.htmlEncode = function () {
    return String(this)
        .replace(/&/g, '&amp;')
        .replace(/"/g, '&quot;')
        .replace(/'/g, '&#39;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;');

}

var aString = '<script>alert("I hack your site")</script>';
console.log(aString.htmlEncode());
</script>

Будет выводить: &lt;script&gt;alert(&quot;I hack your site&quot;)&lt;/script&gt;

.htmlEncode () будет доступен для всех строк после определения.

Некромантинг.
Для этого определенно не требуется jQuery!
Вот порт JavaScript из System.Web.HttpUtility (C# - отказ от ответственности: не очень протестирован):

      "use strict";
function htmlDecode(s) {
    if (s == null)
        return null;
    if (s.length == 0)
        return "";
    if (s.indexOf('&') == -1)
        return s;
    function isDigit(str) {
        return /^\d+$/.test(str);
    }
    function isHexDigit(str) {
        return /[0-9A-Fa-f]{6}/g.test(str);
    }
    function initEntities() {
        var entities = {};
        entities["nbsp"] = '\u00A0';
        entities["iexcl"] = '\u00A1';
        entities["cent"] = '\u00A2';
        entities["pound"] = '\u00A3';
        entities["curren"] = '\u00A4';
        entities["yen"] = '\u00A5';
        entities["brvbar"] = '\u00A6';
        entities["sect"] = '\u00A7';
        entities["uml"] = '\u00A8';
        entities["copy"] = '\u00A9';
        entities["ordf"] = '\u00AA';
        entities["laquo"] = '\u00AB';
        entities["not"] = '\u00AC';
        entities["shy"] = '\u00AD';
        entities["reg"] = '\u00AE';
        entities["macr"] = '\u00AF';
        entities["deg"] = '\u00B0';
        entities["plusmn"] = '\u00B1';
        entities["sup2"] = '\u00B2';
        entities["sup3"] = '\u00B3';
        entities["acute"] = '\u00B4';
        entities["micro"] = '\u00B5';
        entities["para"] = '\u00B6';
        entities["middot"] = '\u00B7';
        entities["cedil"] = '\u00B8';
        entities["sup1"] = '\u00B9';
        entities["ordm"] = '\u00BA';
        entities["raquo"] = '\u00BB';
        entities["frac14"] = '\u00BC';
        entities["frac12"] = '\u00BD';
        entities["frac34"] = '\u00BE';
        entities["iquest"] = '\u00BF';
        entities["Agrave"] = '\u00C0';
        entities["Aacute"] = '\u00C1';
        entities["Acirc"] = '\u00C2';
        entities["Atilde"] = '\u00C3';
        entities["Auml"] = '\u00C4';
        entities["Aring"] = '\u00C5';
        entities["AElig"] = '\u00C6';
        entities["Ccedil"] = '\u00C7';
        entities["Egrave"] = '\u00C8';
        entities["Eacute"] = '\u00C9';
        entities["Ecirc"] = '\u00CA';
        entities["Euml"] = '\u00CB';
        entities["Igrave"] = '\u00CC';
        entities["Iacute"] = '\u00CD';
        entities["Icirc"] = '\u00CE';
        entities["Iuml"] = '\u00CF';
        entities["ETH"] = '\u00D0';
        entities["Ntilde"] = '\u00D1';
        entities["Ograve"] = '\u00D2';
        entities["Oacute"] = '\u00D3';
        entities["Ocirc"] = '\u00D4';
        entities["Otilde"] = '\u00D5';
        entities["Ouml"] = '\u00D6';
        entities["times"] = '\u00D7';
        entities["Oslash"] = '\u00D8';
        entities["Ugrave"] = '\u00D9';
        entities["Uacute"] = '\u00DA';
        entities["Ucirc"] = '\u00DB';
        entities["Uuml"] = '\u00DC';
        entities["Yacute"] = '\u00DD';
        entities["THORN"] = '\u00DE';
        entities["szlig"] = '\u00DF';
        entities["agrave"] = '\u00E0';
        entities["aacute"] = '\u00E1';
        entities["acirc"] = '\u00E2';
        entities["atilde"] = '\u00E3';
        entities["auml"] = '\u00E4';
        entities["aring"] = '\u00E5';
        entities["aelig"] = '\u00E6';
        entities["ccedil"] = '\u00E7';
        entities["egrave"] = '\u00E8';
        entities["eacute"] = '\u00E9';
        entities["ecirc"] = '\u00EA';
        entities["euml"] = '\u00EB';
        entities["igrave"] = '\u00EC';
        entities["iacute"] = '\u00ED';
        entities["icirc"] = '\u00EE';
        entities["iuml"] = '\u00EF';
        entities["eth"] = '\u00F0';
        entities["ntilde"] = '\u00F1';
        entities["ograve"] = '\u00F2';
        entities["oacute"] = '\u00F3';
        entities["ocirc"] = '\u00F4';
        entities["otilde"] = '\u00F5';
        entities["ouml"] = '\u00F6';
        entities["divide"] = '\u00F7';
        entities["oslash"] = '\u00F8';
        entities["ugrave"] = '\u00F9';
        entities["uacute"] = '\u00FA';
        entities["ucirc"] = '\u00FB';
        entities["uuml"] = '\u00FC';
        entities["yacute"] = '\u00FD';
        entities["thorn"] = '\u00FE';
        entities["yuml"] = '\u00FF';
        entities["fnof"] = '\u0192';
        entities["Alpha"] = '\u0391';
        entities["Beta"] = '\u0392';
        entities["Gamma"] = '\u0393';
        entities["Delta"] = '\u0394';
        entities["Epsilon"] = '\u0395';
        entities["Zeta"] = '\u0396';
        entities["Eta"] = '\u0397';
        entities["Theta"] = '\u0398';
        entities["Iota"] = '\u0399';
        entities["Kappa"] = '\u039A';
        entities["Lambda"] = '\u039B';
        entities["Mu"] = '\u039C';
        entities["Nu"] = '\u039D';
        entities["Xi"] = '\u039E';
        entities["Omicron"] = '\u039F';
        entities["Pi"] = '\u03A0';
        entities["Rho"] = '\u03A1';
        entities["Sigma"] = '\u03A3';
        entities["Tau"] = '\u03A4';
        entities["Upsilon"] = '\u03A5';
        entities["Phi"] = '\u03A6';
        entities["Chi"] = '\u03A7';
        entities["Psi"] = '\u03A8';
        entities["Omega"] = '\u03A9';
        entities["alpha"] = '\u03B1';
        entities["beta"] = '\u03B2';
        entities["gamma"] = '\u03B3';
        entities["delta"] = '\u03B4';
        entities["epsilon"] = '\u03B5';
        entities["zeta"] = '\u03B6';
        entities["eta"] = '\u03B7';
        entities["theta"] = '\u03B8';
        entities["iota"] = '\u03B9';
        entities["kappa"] = '\u03BA';
        entities["lambda"] = '\u03BB';
        entities["mu"] = '\u03BC';
        entities["nu"] = '\u03BD';
        entities["xi"] = '\u03BE';
        entities["omicron"] = '\u03BF';
        entities["pi"] = '\u03C0';
        entities["rho"] = '\u03C1';
        entities["sigmaf"] = '\u03C2';
        entities["sigma"] = '\u03C3';
        entities["tau"] = '\u03C4';
        entities["upsilon"] = '\u03C5';
        entities["phi"] = '\u03C6';
        entities["chi"] = '\u03C7';
        entities["psi"] = '\u03C8';
        entities["omega"] = '\u03C9';
        entities["thetasym"] = '\u03D1';
        entities["upsih"] = '\u03D2';
        entities["piv"] = '\u03D6';
        entities["bull"] = '\u2022';
        entities["hellip"] = '\u2026';
        entities["prime"] = '\u2032';
        entities["Prime"] = '\u2033';
        entities["oline"] = '\u203E';
        entities["frasl"] = '\u2044';
        entities["weierp"] = '\u2118';
        entities["image"] = '\u2111';
        entities["real"] = '\u211C';
        entities["trade"] = '\u2122';
        entities["alefsym"] = '\u2135';
        entities["larr"] = '\u2190';
        entities["uarr"] = '\u2191';
        entities["rarr"] = '\u2192';
        entities["darr"] = '\u2193';
        entities["harr"] = '\u2194';
        entities["crarr"] = '\u21B5';
        entities["lArr"] = '\u21D0';
        entities["uArr"] = '\u21D1';
        entities["rArr"] = '\u21D2';
        entities["dArr"] = '\u21D3';
        entities["hArr"] = '\u21D4';
        entities["forall"] = '\u2200';
        entities["part"] = '\u2202';
        entities["exist"] = '\u2203';
        entities["empty"] = '\u2205';
        entities["nabla"] = '\u2207';
        entities["isin"] = '\u2208';
        entities["notin"] = '\u2209';
        entities["ni"] = '\u220B';
        entities["prod"] = '\u220F';
        entities["sum"] = '\u2211';
        entities["minus"] = '\u2212';
        entities["lowast"] = '\u2217';
        entities["radic"] = '\u221A';
        entities["prop"] = '\u221D';
        entities["infin"] = '\u221E';
        entities["ang"] = '\u2220';
        entities["and"] = '\u2227';
        entities["or"] = '\u2228';
        entities["cap"] = '\u2229';
        entities["cup"] = '\u222A';
        entities["int"] = '\u222B';
        entities["there4"] = '\u2234';
        entities["sim"] = '\u223C';
        entities["cong"] = '\u2245';
        entities["asymp"] = '\u2248';
        entities["ne"] = '\u2260';
        entities["equiv"] = '\u2261';
        entities["le"] = '\u2264';
        entities["ge"] = '\u2265';
        entities["sub"] = '\u2282';
        entities["sup"] = '\u2283';
        entities["nsub"] = '\u2284';
        entities["sube"] = '\u2286';
        entities["supe"] = '\u2287';
        entities["oplus"] = '\u2295';
        entities["otimes"] = '\u2297';
        entities["perp"] = '\u22A5';
        entities["sdot"] = '\u22C5';
        entities["lceil"] = '\u2308';
        entities["rceil"] = '\u2309';
        entities["lfloor"] = '\u230A';
        entities["rfloor"] = '\u230B';
        entities["lang"] = '\u2329';
        entities["rang"] = '\u232A';
        entities["loz"] = '\u25CA';
        entities["spades"] = '\u2660';
        entities["clubs"] = '\u2663';
        entities["hearts"] = '\u2665';
        entities["diams"] = '\u2666';
        entities["quot"] = '\u0022';
        entities["amp"] = '\u0026';
        entities["lt"] = '\u003C';
        entities["gt"] = '\u003E';
        entities["OElig"] = '\u0152';
        entities["oelig"] = '\u0153';
        entities["Scaron"] = '\u0160';
        entities["scaron"] = '\u0161';
        entities["Yuml"] = '\u0178';
        entities["circ"] = '\u02C6';
        entities["tilde"] = '\u02DC';
        entities["ensp"] = '\u2002';
        entities["emsp"] = '\u2003';
        entities["thinsp"] = '\u2009';
        entities["zwnj"] = '\u200C';
        entities["zwj"] = '\u200D';
        entities["lrm"] = '\u200E';
        entities["rlm"] = '\u200F';
        entities["ndash"] = '\u2013';
        entities["mdash"] = '\u2014';
        entities["lsquo"] = '\u2018';
        entities["rsquo"] = '\u2019';
        entities["sbquo"] = '\u201A';
        entities["ldquo"] = '\u201C';
        entities["rdquo"] = '\u201D';
        entities["bdquo"] = '\u201E';
        entities["dagger"] = '\u2020';
        entities["Dagger"] = '\u2021';
        entities["permil"] = '\u2030';
        entities["lsaquo"] = '\u2039';
        entities["rsaquo"] = '\u203A';
        entities["euro"] = '\u20AC';
        return entities;
    }
    var Entities = initEntities();
    var rawEntity = [];
    var entity = [];
    var output = [];
    var len = s.length;
    var state = 0;
    var number = 0;
    var is_hex_value = false;
    var have_trailing_digits = false;
    for (var i = 0; i < len; i++) {
        var c = s[i];
        if (state == 0) {
            if (c == '&') {
                entity.push(c);
                rawEntity.push(c);
                state = 1;
            }
            else {
                output.push(c);
            }
            continue;
        }
        if (c == '&') {
            state = 1;
            if (have_trailing_digits) {
                entity.push(number.toString());
                have_trailing_digits = false;
            }
            output.push(entity.join(""));
            entity = [];
            entity.push('&');
            continue;
        }
        if (state == 1) {
            if (c == ';') {
                state = 0;
                output.push(entity.join(""));
                output.push(c);
                entity = [];
            }
            else {
                number = 0;
                is_hex_value = false;
                if (c != '#') {
                    state = 2;
                }
                else {
                    state = 3;
                }
                entity.push(c);
                rawEntity.push(c);
            }
        }
        else if (state == 2) {
            entity.push(c);
            if (c == ';') {
                var key = entity.join("");
                if (key.length > 1 && Entities.hasOwnProperty(key.substr(1, key.length - 2)))
                    key = Entities[key.substr(1, key.length - 2)].toString();
                output.push(key);
                state = 0;
                entity = [];
                rawEntity = [];
            }
        }
        else if (state == 3) {
            if (c == ';') {
                if (number == 0)
                    output.push(rawEntity.join("") + ";");
                else if (number > 65535) {
                    output.push("&#");
                    output.push(number.toString());
                    output.push(";");
                }
                else {
                    output.push(String.fromCharCode(number));
                }
                state = 0;
                entity = [];
                rawEntity = [];
                have_trailing_digits = false;
            }
            else if (is_hex_value && isHexDigit(c)) {
                number = number * 16 + parseInt(c, 16);
                have_trailing_digits = true;
                rawEntity.push(c);
            }
            else if (isDigit(c)) {
                number = number * 10 + (c.charCodeAt(0) - '0'.charCodeAt(0));
                have_trailing_digits = true;
                rawEntity.push(c);
            }
            else if (number == 0 && (c == 'x' || c == 'X')) {
                is_hex_value = true;
                rawEntity.push(c);
            }
            else {
                state = 2;
                if (have_trailing_digits) {
                    entity.push(number.toString());
                    have_trailing_digits = false;
                }
                entity.push(c);
            }
        }
    }
    if (entity.length > 0) {
        output.push(entity.join(""));
    }
    else if (have_trailing_digits) {
        output.push(number.toString());
    }
    return output.join("");
}
function htmlEncode(s) {
    if (s == null)
        return null;
    if (s.length == 0)
        return s;
    var needEncode = false;
    for (var i = 0; i < s.length; i++) {
        var c = s[i];
        if (c == '&' || c == '"' || c == '<' || c == '>' || c.charCodeAt(0) > 159
            || c == '\'') {
            needEncode = true;
            break;
        }
    }
    if (!needEncode)
        return s;
    var output = [];
    var len = s.length;
    for (var i = 0; i < len; i++) {
        var ch = s[i];
        switch (ch) {
            case '&':
                output.push("&amp;");
                break;
            case '>':
                output.push("&gt;");
                break;
            case '<':
                output.push("&lt;");
                break;
            case '"':
                output.push("&quot;");
                break;
            case '\'':
                output.push("&#39;");
                break;
            case '\uff1c':
                output.push("&#65308;");
                break;
            case '\uff1e':
                output.push("&#65310;");
                break;
            default:
                if (ch.charCodeAt(0) > 159 && ch.charCodeAt(0) < 256) {
                    output.push("&#");
                    output.push(ch.charCodeAt(0).toString());
                    output.push(";");
                }
                else
                    output.push(ch);
                break;
        }
    }
    return output.join("");
}

Используя некоторые другие ответы здесь, я сделал версию, которая заменяет все соответствующие символы за один проход, независимо от количества различных закодированных символов (только один вызов replace()) так будет быстрее для больших строк.

Он не зависит от существования DOM API или других библиотек.

window.encodeHTML = (function() {
    function escapeRegex(s) {
        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
    }
    var encodings = {
        '&'  : '&amp;',
        '"'  : '&quot;',
        '\'' : '&#39;',
        '<'  : '&lt;',
        '>'  : '&gt;',
        '\\' : '&#x2F;'
    };
    function encode(what) { return encodings[what]; };
    var specialChars = new RegExp('[' +
        escapeRegex(Object.keys(encodings).join('')) +
    ']', 'g');

    return function(text) { return text.replace(specialChars, encode); };
})();

Запустив это один раз, теперь вы можете позвонить

encodeHTML('<>&"\'')

Получить &lt;&gt;&amp;&quot;&#39;

Выбирая что escapeHTML() делает в prototype.js

Добавление этого скрипта поможет вам избежать HTML:

String.prototype.escapeHTML = function() { 
    return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;')
}

теперь вы можете вызывать метод escapeHTML для строк в вашем скрипте, например:

var escapedString = "<h1>this is HTML</h1>".escapeHTML();
// gives: "&lt;h1&gt;this is HTML&lt;/h1&gt;"

Надеюсь, это поможет любому, кто ищет простое решение, без необходимости включать весь prototype.js

function encodeHTML(str) {
    return document.createElement("a").appendChild( 
        document.createTextNode(str)).parentNode.innerHTML;
};

function decodeHTML(str) {
    var element = document.createElement("a"); 
    element.innerHTML = str;
    return element.textContent;
};
var str = "<"
var enc = encodeHTML(str);
var dec = decodeHTML(enc);
console.log("str: " + str, "\nenc: " + enc, "\ndec: " + dec);

Другие вопросы по тегам