【问题标题】:Access javascript strict function访问javascript严格函数
【发布时间】:2015-01-29 07:34:21
【问题描述】:

我正在学习 Javascript 的“使用严格”模式,遇到了一个小问题。如果我的理解有问题,请纠正我。

file1.js

(function () {
    'use strict';

     var testObject = {
            "id" : 1,
            "label" : "Object 1"
        };

     printUserInformation = function (userName){
          console.log(" Test Object is "+testObject + " User is "+ userName );
     }
});

file2.js

printUserInformation("StackOverflow User");

但是当我从外部严格模式调用/调用函数时得到未定义的错误,并且也无法访问 testObject。任何指南都会很有用。

【问题讨论】:

  • 从这个 jsFiddle:jsfiddle.net/w3aay7ju 我得到ReferenceError: printUserInformation is not defined
  • 所以你得到了一个未执行的严格函数,它包含一个局部变量和一个隐式全局变量。
  • use strict; 必须出现在文件顶部不是吗
  • @surajck:不,那不正确。
  • @surajck:比这稍微复杂一些,但基本上是的。

标签: javascript function strict


【解决方案1】:

主要问题与严格模式无关。您的 printUserInformation 函数的范围仅限于您放入的匿名函数,它不是全局的,因此 file2.js 无权访问它。还有一些其他问题:你永远不会调用你的作用域函数,所以它里面的代码(包括定义 printUserInformation 的代码永远不会运行),如果它是它会抛出一个 ReferenceError 因为你试图分配到一个未声明的变量(printUserInformation),这会在严格模式下导致错误。

如果您只想为file1.js 启用严格模式而不避免创建全局变量,则不需要范围函数:

'use strict';

var testObject = {
       "id" : 1,
       "label" : "Object 1"
};

var printUserInformation = function (userName){
      console.log(" Test Object is "+testObject + " User is "+ userName );
};

这解决了所有三个问题。前两个是通过删除作用域函数来处理的(但这确实意味着代码创建了两个全局变量);第三个(未声明的变量)通过在以printUserInformation = function... 开头的行前添加var 来修复。我还在该函数表达式的末尾添加了一个;,因为您希望在赋值语句的末尾添加一个;


在您提出的评论中:

你能告诉我如何使用(function () { printUserInformation ..... })访问

如果您想使用范围函数(这通常是一个好主意)但在其中创建全局变量,您有几个选择:

  1. 在调用时从作用域函数中返回要公开的内容

  2. 通过分配给全局对象的属性在作用域函数中创建全局

这是 #1 的样子:

var printUserInformation = (function() {
    'use strict';

    var testObject = {
           "id" : 1,
           "label" : "Object 1"
    };

    var printUserInformation = function (userName){
          console.log(" Test Object is "+testObject + " User is "+ userName );
    };

    return printUserInformation;
})();

请注意,我们不仅定义了作用域函数,而且我们调用它(最后的()),问题中的代码中缺少它。

在那里,testObject 仍然被很好地包含(它不是全局的),但 printUserInformation 是一个全局的。

我应该注意,包裹 函数的括号在那里并不是绝对必要的,但是如果我们没有在某处分配结果,那么它们是必需的,人们习惯于看到它们. var x = function() { return 42; }(); 有效x 将是 42),但可能会扔人。

这是#2 的众多外观之一:

(function(global) {
    'use strict';

    var testObject = {
           "id" : 1,
           "label" : "Object 1"
    };

    global.printUserInformation = function (userName){
          console.log(" Test Object is "+testObject + " User is "+ userName );
    };
})(this);

在全局范围而非严格模式下,this 指的是全局对象。所以我们将该引用作为参数global 传递给作用域函数。严格模式在作用域函数有效,但不在其外。

在浏览器上,您可以使用window,而不是使用this,它是引用全局对象的全局对象(例如,全局变量)的属性。所以你可以这样做:

(function() {
    'use strict';

    var testObject = {
           "id" : 1,
           "label" : "Object 1"
    };

    window.printUserInformation = function (userName){
          console.log(" Test Object is "+testObject + " User is "+ userName );
    };
})();

但这只是在浏览器上,而不是在其他环境(NodeJS、SilkJS 等)中。

使用范围函数真的很方便。在像浏览器这样的环境中,全局命名空间真的很拥挤,避免创建全局变量是一件好事(tm)。如果您不使用 AMD(RequireJS 等),通常最好只创建 一个 全局的,这是一个您可以放置​​其他任何东西的对象。其模式如下所示:

// This bit is in each file: It creates the `MyApp` global and
// initializes it with a blank object if it doesn't already exist,
// or just uses the existing MyApp object if it already exists.
var MyApp = window.MyApp || {};

// Then we define this file's contents inside a scoping function
(function() {
    "use strict";

    // ...private stuff here...

    // Let's make one public function
    MyApp.printUserInformation = function() { /* ... */ };
})();

(并且在非浏览器环境下,可以将上面的window改为this。)

【讨论】:

  • 试过这个:jsfiddle.net/w3aay7ju/3 它有效。所以问题在于范围而不是use strict
  • Thnx 很多,你能告诉我如何使用 (function () { printUserInformation ..... }) 访问
  • @T.J.克劳德,你是对的,我只是习惯于重复一些东西以使自己理解。没有什么可以偷走任何人的风头。
  • @DigitalAlchemist:我第一次听说你。 :-) 我已经更新了答案来解决这个问题。
猜你喜欢
  • 2013-02-14
  • 2011-08-26
  • 2015-03-06
  • 1970-01-01
  • 2021-02-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多