【问题标题】:What does this Javascript code do?这段 Javascript 代码有什么作用?
【发布时间】:2011-05-09 18:51:53
【问题描述】:

我一直在查看 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 了如指掌…… ;) 一定是我过去从未使用过的一些晦涩的功能,而且显然其他人也很少使用。

【问题讨论】:

    标签: javascript sharepoint sharepoint-2010


    【解决方案1】:

    想了很久,终于坐下来解决了。这都是在客户端收集诊断信息的相对复杂机制的一部分,其中包括将 javascript 调用堆栈(包括函数名称和 javascript 文件)发送回服务器的能力。

    查看文件 init.debug.js 的前 250 行 ,它位于

    %Program Files%\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\1033\init.debug.js

    此文件定义了客户端上“ULS”实现的所有功能。

    当然,您需要安装 SharePoint 2010 才能使该文件存在于您的本地计算机上。

    更新 -- 以下是该机制大致如何工作的概述。真正的实现不止于此

    考虑以下带有几个 js 包含的 html 页面,每个都可以相互调用。

    <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包含文件,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
    

    【讨论】:

    • 或许您可以解释一下为什么这个“复杂”机制需要一个完全无用的标签,以及如何使用它。参考一个相对少数人拥有的文件并说“阅读这个”是没有帮助的。
    • 当然...我不会发布 Microsoft 的 js 代码,但我会添加一个简化的示例来展示它的工作原理。
    • 所以你说它依赖于在函数上使用toString(它从未被标准化并且在某些移动浏览器上不起作用),它依赖于函数的字符串表示没有通过优化删除无用的标签。有趣的是,我想我会走另一条路。不过,好的答案,+1。
    • 谢谢。只是最后一点,实际的实现将尽其所能收集浏览器可以提供的任何信息,并在必要时优雅地降级。请记住,这是 SharePoint 代码,因此最适合 Internet Explorer。
    【解决方案2】:

    第一位定义了一个函数,它创建一个具有几个属性的对象并返回它。我想我们都清楚这一点。 :-)

    不过,第二点是没有使用那个功能。它定义了一个具有相同名称的 label。虽然它使用相同的字符序列,但它不是对上述函数的引用。 Firefox 的解释和其他任何东西一样有意义,因为标签后面应该跟着它可以引用的东西。

    有关标记语句的更多信息,请参阅the spec 的第 12.12 节。


    题外话:我会避免使用此来源的代码。编写它的人显然对 JavaScript 来说相当新,并且没有表现出太多迹象表明他们知道自己在做什么。例如,他们已经将() 留在了new Object() 呼叫之外,虽然这是允许的,但这是相当狡猾的事情。他们可能会争辩说他们这样做是为了节省空间,但如果是这样,他们最好还是使用对象字面量:

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

    根本没有太多理由写new Object(){} 功能相同。

    当然,第二位完全没有理由。 :-)

    【讨论】:

    • 不会是微软开发人员吧? :)
    • 我会避免使用这个来源的代码。写它的人显然是 JavaScript 的新手,并没有表现出太多迹象表明他们知道自己在做什么。 -> 告诉微软!有趣的是,这个脚本是由 Microsoft stuff 编写的,并且是 Sharepoint Foundation 2010 的一部分。:) 这是SP.UI.Dialog.Debug.js 文件的第一个位......我不认为他们是经验不足。 ;)
    • @Robert:微软作为一个整体可能并非没有经验,但不要认为他们没有经验不足的开发人员,而且其中一些有时可能不会渗透。上面引用的代码要么是由一个不知道自己在做什么的人编写的,是由一个有点发疯的自动生成器创建的(可能是输入无效输入),要么是(当然!)是我的构造陌生。我对 JavaScript 了解很多,但对它却一无所知。 :-) 例如,如果您不了解严格模式,那么函数顶部只有 "use strict"; 的一行看起来毫无意义。
    • 你是对的。这简直是​​愚蠢的。因为没有代码会引用这些标签中的任何一个。一些没有经验的开发人员显然复制了其他一些他自己不理解的函数定义。我想。这简直是​​愚蠢的。
    • @Robert:这是一个关于标签范围的好问题。它在第 12.12 节中有介绍,但是这种语言非常陈旧,很难说出它在说什么。基本上,标签的范围仅限于它们标记的语句和该语句的内容。每条语句都以一个空标签集开始,如果它为语句添加标签,则会向该标签集添加标签。由于您可以嵌套语句(for 中的switch),因此您最终可能会在集合中得到多个标签,但是一旦您离开标签标签的语句,标签就不再存在。例如:jsbin.com/emavi4 第二个循环看不到第一个的标签。
    【解决方案3】:

    不就是statement label吗?我认为标签与早期函数同名的事实并不意味着什么。

    【讨论】:

      【解决方案4】:

      看起来,它创建了一个应该填充一些数据的空对象,但由于创建此代码的代码生成器没有被删除,所以它坐在那里是空的

      【讨论】:

      • 创建一个对象意味着使用不存在的赋值运算符 (=)(冒号是)。 whatever-it-is... 的末尾还缺少一个分号
      猜你喜欢
      • 1970-01-01
      • 2010-11-07
      • 2011-04-13
      • 1970-01-01
      • 1970-01-01
      • 2013-12-19
      • 2011-06-01
      相关资源
      最近更新 更多