Что делает этот код Javascript?
Я смотрел файлы Sharepoint script, и я натолкнулся на этот бит, который я не получаю:
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 через и......) Должна быть какая-то неясная особенность, которую я никогда не использовал в прошлом, и, очевидно, редко используется и другими.
Ответы
Ответ 1
Первый бит определяет функцию, которая создает объект с несколькими свойствами и возвращает его. Я думаю, что мы все поняли.: -)
Второй бит, однако, не использует эту функцию. Он определяет метку с тем же именем. Хотя он использует одну и ту же последовательность символов, это не ссылка на вышеприведенную функцию. Интерпретация Firefox делает такой же смысл, как и все остальное, потому что за ярлыком должно следовать что-то, на что оно может ссылаться.
Подробнее о помеченных инструкциях см. Раздел 12.12 спецификация.
Вне темы. Я бы не использовал код из этого источника. Тот, кто написал это, по-видимому, довольно новичок в JavaScript и не показывает много признаков того, что они знают, что они делают. Например, они вышли из ()
с вызова new Object()
, и, хотя это разрешено, это довольно хитроумная вещь. Они могут утверждать, что они делали это, чтобы сэкономить место, но если бы они были, им было бы лучше использовать объектный литерал:
function ULSTYE() {
return {
ULSTeamName: "Microsoft SharePoint Foundation",
ULSFileName: "SP.UI.Dialog.debug.js"
};
}
Там никогда не бывает причин писать new Object()
вообще; {}
является функционально идентичным.
И, конечно, нет никакого оправдания для второго бит вообще.: -)
Ответ 2
Подумав об этом в течение долгого времени, я наконец сел и обработал его. Все это является частью относительно сложного механизма сбора диагностической информации о клиенте, которая включает в себя возможность отправки javascript callstack (включая имя функции и файл javascript) обратно на сервер.
Взгляните на первые 250 строк файла init.debug.js, который находится в
% Program Files%\Common Files\Microsoft Shared\Расширения веб-сервера\14\TEMPLATE\LAYOUTS\1033\init.debug.js
Этот файл определяет все функции реализации ULS на клиенте.
Конечно, вам необходимо установить SharePoint 2010 для существования файла на вашей локальной машине.
ОБНОВЛЕНИЕ - Ниже приведен краткий обзор того, как работает механизм. Реальная реализация делает больше, чем этот
Рассмотрим следующую страницу html с несколькими js include, каждая из которых может вызывать друг друга.
<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);
}
Когда мы нажимаем кнопку на странице, наш script файл вызывается через каждую из функций и заканчивается в DisplayCallStack, после чего он будет рекурсивно проходить цикл и собирать трассировку стека
Error! Testing
Function: DoEvenMoreStuff => Script file: File2.js
Function: DoMoreStuff => Script file: File2.js
Function: DoStuff => Script file: File1.js
Function: onclick
Ответ 3
Разве это не просто метка оператора? Я думаю, что ярлык имеет то же имя, что и более ранняя функция.
Ответ 4
он выглядит, как будто он создает пустой объект, который должен быть заполнен некоторыми данными, но из-за генератора кода, который создает этот код, он не удаляется, поэтому он сидит там пустой