jQuery/JavaScript功能范围/提升

jQuery/JavaScript功能范围/提升,javascript,jquery,Javascript,Jquery,我有两个包含JavaScript和jQuery函数的文件。它们在页面上的引用顺序如下: <script src="js/kiosk-functions.js"></script> <script src="js/kiosk-main-socket-handler.js"></script> 然后,在kiosk-main.js中,我有一个- $(function() { var socket = io(); socket.on('m

我有两个包含JavaScript和jQuery函数的文件。它们在页面上的引用顺序如下:

<script src="js/kiosk-functions.js"></script>
<script src="js/kiosk-main-socket-handler.js"></script>
然后,在kiosk-main.js中,我有一个-

$(function() {
    var socket = io();
    socket.on('message', function (data) {

        if(isJSON(data)) {
            // do stuff
        }
    });
    // other JavaScript and jQuery code
});
这导致了以下错误-

未捕获引用错误:未定义isJSON

一旦我将
isJSON()
函数移出kiosk-functions.js中的文档就绪处理程序,一切都很好,但让我感到困惑。我在这里读了很多答案,所以我试图理解到底发生了什么,因为我的印象是,这个功能将被提升并在全球范围内可用。我没有找到任何能证明这个例子的东西

我确信我在这里遗漏了一些简单的东西。文档就绪处理程序(一个函数)是否阻止了
isJSON()
函数被提升?或者这是一个简单的范围问题?

$(function(){})
只是
$(document.ready(function(){})的一个较短版本

在上述函数中,
文档
,要使函数成为全局函数,它需要位于
窗口
上下文中

提升不是您的问题,声明函数的范围是

如果它在代码中被广泛使用,并且不是您正在构建的特定模块或库的一部分,那么您可以在全局上下文中声明函数,或者只创建函数,
window
的属性使其成为全局函数

如果是某个库或模块,则可以将其附加到该库或模块,使其仅特定于该库/模块


简而言之,如果您确实多次使用名称空间,并且它是一个通用函数,请使用名称空间或使其成为全局的。

您的问题不在于提升,而在于函数的范围

基本上,在
kiosk functions.js
中定义对
document.ready
的回调,并在该回调中定义函数
isJSON()
。该函数仅在该范围内已知

在第二个文件
kiosk main.js
中,您尝试使用
isJSON()
,就好像它是在回调的作用域或全局作用域中定义的一样。两者都不是这样,因此出现了错误

为了解决这个问题,您可以添加一些全局名称空间
myNamespace
,并将函数附加到其中:

$(function() {
    // some JavaScript functions
    function isJSON(str) {
        try {
            JSON.parse(str);
            return true;
        } catch (e) {
            return false;
        }
     }

  // init namespace
  window.myNamespace = window.myNamespace || {};

  // attach function
  window.myNamespace.isJSON = isJSON;
});
然后在另一个文件中,您可以引用该全局命名空间来调用您的函数:

$(function() {
    var socket = io();
    socket.on('message', function (data) {

        if(myNamespace.isJSON(data)) {
            // do stuff
        }
    });
    // other JavaScript and jQuery code
});

编辑


正如@Alnitak在评论中提到的:在浏览器中,全局对象是
窗口
。相应地更改了代码。

变量和函数定义仅在封闭的函数范围内提升,在您的情况下,这是您传递给
$()
的匿名函数。在这方面,提升并没有什么不同,只是
isJSON
函数定义在不同的范围内

您可能希望考虑模块命名空间模式:

var NAMESPACE = NAMESPACE || {};

NAMESPACE.isJSON = function() {
    ...
};
其中
NAMESPACE
是一个全局变量,它将包含所有本地定义的函数


名称空间| |{}
用于确保
名称空间
对象如果已经存在,则不会被覆盖。

因此在这种情况下不会发生提升?@JayBlanchard会发生提升,但提升函数与scopeAh有关!现在这是有道理的。javascript是函数范围的(不是说
let
语句)
isJSON
是在ready handler作用域下定义的OP提到的jQuery-很可能他想要
window
而不是
global
。感谢对使用命名空间的解释,我没有机会使用它,但看起来我可以在这个项目上利用它。@JayBlanchard不再,-)谢谢。
var NAMESPACE = NAMESPACE || {};

NAMESPACE.isJSON = function() {
    ...
};