2013-02-28 4 views
4

Вопрос сам по себе пояснительный. Я знаю, что можно распространять примитивные типы данных, такие как string, но можно ли его перезаписать?Возможно ли перезаписать примитивный тип данных javaScript?

Это вопрос, заданный в интервью.

+3

Запишите, что именно? – Bergi

+0

например. String, скажем, строка всегда должна иметь один номер. –

+0

Раньше была возможность переписать конструктор Array, например, но была исправлена ​​из-за связанных с JSON дыр в безопасности, см. Там: http://ejohn.org/blog/re-securing-json/ - говорит, что это невозможно больше переписать конструкторы глобальных объектов, по крайней мере, в FF (предположим, что это относится ко всем основным браузерам). – darma

ответ

2

Нет, вы ничего не можете перезаписать. EcmaScript defines the primitive typesUndefined, Null, Boolean, Number и String; они являются внутренними и будут использоваться независимо от того, что вы делаете (например, перезаписываете глобальный конструктор String). Type conversion и оценка литералов не зависит от каких-либо публичных функций, а использует только эти внутренние типы и алгоритмы, указанные для них.

Конечно, если кто-то делает принуждение строки с String(myval) вместо ""+myval, то присвоение глобальной переменной String повлияет на этот код. Любое внутреннее использование все равно указывает на «старую» функцию.


Если вы говорите об объектах прототипа для примитивных типов (при использовании as objects), тем не перезаписываемые, а также. Вы можете расширять эти объекты, но как только вы назначаете, например, Number.prototype вы только что потеряли ссылку на фактический, оригинальный номер объекта протипа. Пример спецификации для The Number constructor:

код [прототип] создаваемого объекта устанавливается в оригинального Номер объекта-прототипа, тот, который является начальное значение из Number.prototype (15.7.3.1)

1

Да (Редактировать: почти). Откройте консоль JavaScript (F12, если вы используете Chrome) и тип

String = function(){alert('bang!')}; 

Вы можете перезаписать (редактирование: почти) все в Javascript - даже window глобальный контекст! evil.js - это библиотека, которая использует этот трюк, чтобы переписать многие собственные объекты, насколько это возможно.

Излишне говорить, что это очень опасно. Я выполнил код переопределения String выше, и с момента его написания я вызвал более 520 ошибок Javascript (и я видел «взлом», предупрежденный несколько раз). Внутренние объекты используются повсеместно, и вы не должны изменять их, если сторонний код полагается на них способами, о которых вы не знаете. Это одна из причин, по которой потеряла популярность Prototype.js, поскольку ее расширение собственных объектов часто срабатывало против ожиданий другого кода.

Edit: Фактически неправильное утверждение, что абсолютно все может быть перезаписана, как указано в Bergi «s answer. Редактирование сделанных inline.

+0

Есть также зарезервированные ключевые слова, которые невозможно перезаписать (для, выход ...). И для меня окно действительно не может быть перезаписано с помощью Firebug на FF (хотя сначала это не очевидно). – Greg

0

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

function Array() { 
    var obj = this; 
    var ind = 0; 
    var getNext = function(x) { 
    obj[ind++] setter = getNext; 
    if (x) alert("Data stolen from array: " + x.toString()); 
    }; 
    this[ind++] setter = getNext; 
} 
var a = ["private stuff"]; 
// alert("Data stolen from array: private stuff"); 
+0

a) это была ошибка в старом браузере; массивные литералы не вызывают глобальную функцию «Массив» b) ОП задал вопрос о * примитивных * типах. – Bergi

0
  1. Вы можете расширить прототипы встроенных типов.

    String.prototype.moo = function() { 
        console.log('Moo!') 
    }; 
    'Cow says'.moo(); 
    >> "Moo!" 
    
  2. Однако вы не можете непосредственно перезаписать конструкторы встроенных типов, если вы не перезаписать ссылку на весь объект:

    String = function() { 
        console.log('Custom function.') 
    }; 
    
    new String('Hello!'); 
    >> "Custom function." 
    >> String {} // now you've broken your website ;) 
    
  3. ... но все же:

    'Wat?!' 
    >> "Wat?!" // you can still create strings by typing letters in quotes 
    

Итак ... ответ «да, но нет». Вы можете общаться с родными типами (Number, Date, String ...), но вы не можете их полностью переформулировать с нуля. Они являются частью JS-движка, который вы используете (скорее всего, родной код C++), и это приносит некоторые ограничения.

+2

Обратите внимание, что 'X.prototype.constructor' фактически не используется внутренне, для любого типа (пользовательского или встроенного), поэтому его изменение никогда не будет иметь никакого эффекта. Это просто справочная информация для конструктора для пользователя. –

+0

'Math' нет типа. – Bergi

+0

@Bergi Совершенно верно. Хорошо поймал! – oleq

Смежные вопросы