Что делает этот код Javascript? - PullRequest
17 голосов
/ 14 ноября 2010

Я просматривал файлы сценариев Sharepoint, и мне попался этот бит, который я не получаю:

function ULSTYE() {
    var o = new Object;
    o.ULSTeamName = "Microsoft SharePoint Foundation";
    o.ULSFileName = "SP.UI.Dialog.debug.js";

    return o;
}

SP.UI.$create_DialogOptions = function() {
    ULSTYE:;   <----------------------------- WTF?
    return new SP.UI.DialogOptions();
}

На самом деле каждая функция определение в этом файле начинается с той же строки ULSTYE:; сразу после открывающей фигурной скобки. Кто-нибудь может объяснить, что делает первая строка во второй функции?

Например, Firefox / Firebug интерпретирует эту функцию как нечто, чего я не могу понять:

function () {
    ULSTYE: {
    }
    return new (SP.UI.DialogOptions);
}

И мне показалось, что я знаю Javascript насквозь ... ;) Должно быть, это какая-то неясная особенность, которой я никогда не пользовался в прошлом и, очевидно, редко используется другими.

Ответы [ 4 ]

21 голосов
/ 25 сентября 2011

После долгих размышлений об этом я, наконец, сел и решил. Все это является частью относительно сложного механизма сбора диагностической информации на клиенте, который включает в себя возможность отправки стека вызовов javascript (включая имя функции и файл javascript) обратно на сервер.

Посмотрите на первые 250 строк файла init.debug.js , который находится в

% Программные файлы% \ Common Files \ Microsoft Shared \ Расширения веб-сервера \ 14 \ TEMPLATE \ LAYOUTS \ 1033 \ init.debug.js

Этот файл определяет все функции, которые реализует ULS на клиенте.

Конечно, вам нужно установить SharePoint 2010, чтобы файл существовал на вашем локальном компьютере.

ОБНОВЛЕНИЕ - Ниже приведено общее представление о том, как работает механизм. Реальная реализация делает больше, чем это

Рассмотрим следующую html-страницу с несколькими js-включениями, каждая из которых может вызывать друг друга.

<html>
 <head>
   <script type="text/javascript" src="ErrorHandling.js"></script>
   <script type="text/javascript" src="File1.js"></script>
   <script type="text/javascript" src="File2.js"></script>
 </head>
 <body>
   <button onclick="DoStuff()">Do stuff</button>
 </body>
</html>

У нас есть два файла js include, File1.js

    function ULSabc() { var o = new Object; o.File = "File1.js"; return o; }
    /* ULSabc is the unique label for this js file. Each function in 
    this file can be decorated with a label corresponding with the same name */

    function DoStuff() {
        ULSabc: ;
        //label matches name of function above
        DoMoreStuff();
    }

и File2.js

    function ULSdef() { var o = new Object; o.File = "File2.js"; return o; }

    function DoMoreStuff() {
        ULSdef: ;
        DoEvenMoreStuff();
    }

    function DoEvenMoreStuff() {
        ULSdef: ;
        try {
            //throw an error
            throw "Testing";
        } catch (e) {
            //handle the error by displaying the callstack
            DisplayCallStack(e);
        }
    }

Теперь, скажем, наш файл ErrorHandling выглядит следующим образом

    function GetFunctionInfo(fn) {
        var info = "";
        if (fn) {
            //if we have a function, convert it to a string
            var fnTxt = fn.toString();

            //find the name of the function by removing the 'function' and ()
            var fnName = fnTxt.substring(0, fnTxt.indexOf("(")).substring(8);
            info += "Function: " + fnName;

            //next use a regular expression to find a match for 'ULS???:' 
            //which is the label within the function
            var match = fnTxt.match(/ULS[^\s;]*:/);
            if (match) {
                var ULSLabel = match[0];

                //if our function definition contains a label, strip off the 
                // : and add () to make it into a function we can call eval on
                ULSLabel = ULSLabel.substring(0, ULSLabel.length - 1) + "()";

                //eval our function that is defined at the top of our js file
                var fileInfo = eval(ULSLabel);
                if (fileInfo && fileInfo.File) {
                 //add the .File property of the returned object to the info
                    info += " => Script file: " + fileInfo.File;
                }
            }
        }
        return info;
    }

    function DisplayCallStack(e) {
        //first get a reference to the function that call this
        var caller = DisplayCallStack.caller;
        var stack = "Error! " + e + "\r\n";

        //recursively loop through the caller of each function,
        //collecting the function name and script file as we go
        while (caller) {
            stack += GetFunctionInfo(caller) + "\r\n";
            caller = caller.caller;
        }

        //alert the callstack, but we could alternately do something 
        //else like send the info to the server via XmlHttp.
        alert(stack);
    }

Когда мы нажимаем кнопку на странице, наш файл сценария будет вызывать каждую из функций и заканчиваться на DisplayCallStack, после чего он будет рекурсивно проходить по циклу и собирать трассировку стека

    Error! Testing
    Function: DoEvenMoreStuff => Script file: File2.js
    Function: DoMoreStuff     => Script file: File2.js
    Function: DoStuff         => Script file: File1.js
    Function: onclick
14 голосов
/ 14 ноября 2010

Первый бит определяет функцию, которая создает объект с парой свойств и возвращает его. Я думаю, что мы все ясно по этому вопросу. : -)

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

Подробнее о помеченных выражениях см. Раздел 12.12 в спецификации .


Не по теме : я бы не использовал код из этого источника. Кто бы это ни написал, он, очевидно, довольно плохо знаком с JavaScript и не показывает особых признаков того, что знает, что делает. Например, они исключили () из вызова new Object(), и хотя это разрешено, это довольно хитрая вещь. Они могут утверждать, что делают это, чтобы сэкономить место, но если бы они были, им было бы лучше использовать литерал объекта:

function ULSTYE() {
    return {
        ULSTeamName: "Microsoft SharePoint Foundation",
        ULSFileName: "SP.UI.Dialog.debug.js"
    };
}

Нет особой причины писать new Object(); {} функционально идентичен.

И, конечно, нет никакого оправдания второму биту вообще. : -)

4 голосов
/ 14 ноября 2010

Разве это не просто метка оператора ? Думаю, тот факт, что метка имеет то же имя, что и предыдущая функция, ничего не значит.

0 голосов
/ 14 ноября 2010

похоже, что он создает пустой объект, который должен быть заполнен некоторыми данными, но из-за генератора кода, который создает этот код, он не удаляется, поэтому он остается пустым

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...