Это сайт — моя персональная записная книжка. Интересна мне, по большей части, история, своя жизнь и немного программирование.

JavaScript: Недосказанное Нетскейпом

Не оставляя надежду найти аналог CollectGarbage в Netscape, я сегодня расковырял интерпретатор JavaScript’а своего браузера на предмет наличия всего недокументированного. Ковырять вручную было лениво и я сначала написал небольшую программку, вычесывающую все текстовое из файла, на Перле, а потом небольшой скриптик под JUnix, который проверил, что из найденного относится к JavaScript. Ничего похожего на вызов сборщика мусора я так и не нашел, зато нашел кое-что другое. Результатами хочу поделиться.

Script(string) — создает кусок JavaScript-кода, который можно вызвать как обычную функцию. Разница между этим конструктором и Function заключается в том, что из кода, созданного конструктором Script, нельзя получить доступ к arguments и прочим свойствам и методам, специфическим для функций.

Пример использования Script:

AX      = new Script ("alert('TEST')")
AX      ()                      // Нaпечатает "TEST"

Call() — создает пустой объект типа Window. Практической пользы маловато, но, как это можно применить я могу придумать.

Пример того, что можно сделать с Call:

AX      = window
AX.BX   = "TEST"
alert (window.BX)                       // Напечатает "TEST"

window.BX = "TEST1"
AX      = new Call()
AX.BX   = window.BX
window.BX = "TEST2"
alert (AX.BX)                   // Напечатает "TEST2"

AX.open = window.open
AX.open ("about:blank")         // Откроет новое окно

BX      = {}
BX.open = window.open
BX.open ("about:blank")         // Вызовет ошибку

With(object) — достаточно странная функция. Копирует объект на новое место. Конструктор не вызывается, операция сравнения без приведения утверждает, что был создан новый объект, но изменения в одном экземпляре вызывают изменения в другом. Вообще-то, можно ее вызвать, как конструктор без параметров, в этом случае она создаст объект типа Object.

Пример вызова функции With:

function probe ()
{
        alert ('Create.')
        this.let = let
        this.val = val
}

function let (n)
{
        this.val = n
}

AX      = new probe()           // Напечатает "Create"
BX      = AX
alert   (AX===BX)                       // Напечатает "true"

BX      = With (AX)
BX.let  ("TEST")
alert   (AX.val)                        // Напечатает "TEST"
alert   (AX===BX)                       // Напечатает "false"

Closure(function_object) — очень похожа на With, но с парой отличий. Во-первых, Closure работает только с объектами Function, а во-вторых, ее можно вызвать как конструктор. И вот тут начинается самое странное. Внимание на пример.

Пример вызова функции и конструктора Closure:

function let (n)
{
        this.val = n
}

Function.prototype.let = let
AX      = new Function ("","")

BX      = AX
alert   (AX===BX)                       // "true". Объекты одинаковые.
AX.let  ("TEST1")
alert   (BX.val)                        // "TEST1". И это логично.

BX      = Closure (AX)
alert   (AX===BX)                       // "false". Объекты разные.
AX.let  ("OTHER")
alert   (BX.val)                        // "TEST2". И это тоже логично.

BX      = new Closure (AX)
alert   (AX===BX)                       // "false". Объекты разные.
AX.let  ("TEST2")
alert   (BX.val)                        // "TEST2". И это странно.

Arguments(объект) — в принципе можно применять для дублирования массива аргументов. Если применить как функцию, а не как конструктор, то Netscape может обидится и сказать GPF. А вообще во время экспериментов с этим объектом мой NC 4.7 падал настолько часто, что можно сказать — это его больное место, трогать которое не рекомендуется.

Пример вызова конструктора Arguments:

AX      = new Function ("", "return new Arguments(arguments)")
alert   (AX("TEST1").length)            // "1"
alert   (AX("TEST1","TEST2").length)    // "2"

Желающим испытать свое терпение и способности к обобщению, предлагается выяснить, какие функции несет каждый объект, свойство или метод из списка: __count__, __parent__, __proto__, __name__, __length__, __arity__, __call__, __caller__, __callee__. Кое-что совсем очевидно, но кое с чем придется серьезно помучиться. :))

Мое мнение — все, что я накопал, это усы от внутренней объектной модели браузера. Результат попытки упихать все, что только возможно, в объекты.

P.S. Мучал я Netscape версии 4.7. Как нибудь, надеюсь, руки дойдут до чего-нибудь более современного. Кстати, было бы интересно рассмотреть все эти, вырванные с мясом куски, на предмет дыр в безопасности и crash code.