Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
“保护全局Javascript”;空气污染指数;对象_Javascript_Html_Object - Fatal编程技术网

“保护全局Javascript”;空气污染指数;对象

“保护全局Javascript”;空气污染指数;对象,javascript,html,object,Javascript,Html,Object,我目前有一个基于全局Javascript的API运行的Web应用程序,其初始化如下: var Api = { someVar: "test", someFunction: function() { return "foo"; } } Api.myExtension = { myNewFunction: function() { return "bar"; } } 此API在Web应用程序中的许多“小部件”之间共享,它们都

我目前有一个基于全局Javascript的API运行的Web应用程序,其初始化如下:

var Api = {
    someVar: "test",
    someFunction: function() {
        return "foo";
    }
}
Api.myExtension = {
    myNewFunction: function() {
        return "bar";
    }
}
此API在Web应用程序中的许多“小部件”之间共享,它们都应该运行这个
API
实例,以便彼此传递数据

AJAX目前用于加载这些小部件,例如在Widgets/mywidget.html中,它被放置在,比如,

代码的某些其他部分可能会选择向
Api
添加更多功能,目前的做法如下:

var Api = {
    someVar: "test",
    someFunction: function() {
        return "foo";
    }
}
Api.myExtension = {
    myNewFunction: function() {
        return "bar";
    }
}
但是,这种用法会产生一些问题:

问题一:如果一个小部件(可能由第三方提供)决定在其中隐藏一些代码,并执行类似于
Api={}
的操作,破坏了全局
Api
var,破坏了整个应用程序,该怎么办?是否可以保护此
Api
变量不被外部覆盖?只允许“扩展”(添加新事物),但不允许“删除/更改”。i、 e:

Api.foo = { test: "bar" } // allowed
Api.someVar = "changing the existing someVar"; // not allowed
以下代码位于Api的“内部”,例如:

var Api = {
    Debug: {
        Messages = new Array,
        Write: function() {
            Api.Debug.Messages.push("test"); // allowed
        }
    }
}

Api.Debug.Messages.push("test 2"); // not allowed
var Api = {
   widgetApi = {
      someFunction: function(){
          // ...
      }
   },
   addWidget:function(){
      var temp = this.widgetApi.constructor(); 

      for(var key in this.widgetApi)
         temp[key] = clone(this.widgetApi[key]);
      return temp;
   }
   // Include other variables that Widgets can't use
}
我想到的可能解决方案:

  • 假设我们只是使用框架来解决这个问题。提供的
    Api
    s现在彼此独立。但是,如果我有许多运行的
    小部件
    ,并且它们无法再与小部件的“主机”(帧所在的页面)通信,那么在反复加载
    Api
    时会有额外的开销,例如,我可能想告诉主机显示通知:
    Api.Notify.show(“Test”)
    ,但是它不能这样做,因为这个
    Api
    完全独立于其他实例,并且它不能与“主机”通信

  • 使用类似“getter”和“setter”的函数来读取和写入Api。我不确定如何实现这一点,所以欢迎任何关于如何实现这一点的指导帮助

  • 1/2的混合物

  • 保护全局变量的唯一方法(至少我能想到)是防止小部件直接访问它。正如您所建议的,这可以通过使用frames函数来实现。您应该创建一个包含小部件应该能够使用的所有函数的对象,并将这些函数传递给每个小部件。例如:

    var Api = {
        Debug: {
            Messages = new Array,
            Write: function() {
                Api.Debug.Messages.push("test"); // allowed
            }
        }
    }
    
    Api.Debug.Messages.push("test 2"); // not allowed
    
    var Api = {
       widgetApi = {
          someFunction: function(){
              // ...
          }
       },
       addWidget:function(){
          var temp = this.widgetApi.constructor(); 
    
          for(var key in this.widgetApi)
             temp[key] = clone(this.widgetApi[key]);
          return temp;
       }
       // Include other variables that Widgets can't use
    }
    
    通过这种方式,小部件可以执行函数并与主机或全局变量
    Api
    通信。要设置变量,小部件将编辑其私有对象,而不是全局对象。对于每个帧(表示小部件),必须初始化或创建
    widgetApi
    对象的副本,并可能将其存储在一个数组中,以使小部件的实例存储在主
    Api
    对象中

    例如,给定

    您将执行以下操作:

    var widget = document.getElementById("widget");
    widget.contentWindow.Api = Api.addWidget();
    widget.contentWindow.parent = null;
    widget.contentWindow.top = null;
    
    var Api = (function () {
        // private variable
        var myArray = [];
    
        return {
            addItem: function (newItem) {
                myArray.push(newItem);
            },
            printItems: function () {
                console.log("lots if items");
            }
        };
    })();
    
    Api.addItem("Hello, world");
    Api.extensionValue = 5;
    

    此外,在每个帧中,您需要将
    parent
    top
    变量设置为null,以便小部件无法访问主帧的数据。我已经有一段时间没有测试过这个方法了,所以可能有一些方法可以绕过将这些变量设置为null的问题。

    没有好的方法可以防止“第三方”小部件覆盖全局变量。通常,组装最终应用程序的人都有责任确保他们使用的任何Java脚本不会乱丢全局名称空间和冲突。在这个方向上,你能做的最好的事情就是给你的“Api”起一个好的、唯一的名字

    我认为对你有很大帮助的是类似于“揭示模式”的东西,这是一种做你提到的“获得者和设定者”的方式,如果你需要的话,还可以做更多

    一个简单而无用的示例如下所示:

    var widget = document.getElementById("widget");
    widget.contentWindow.Api = Api.addWidget();
    widget.contentWindow.parent = null;
    widget.contentWindow.top = null;
    
    var Api = (function () {
        // private variable
        var myArray = [];
    
        return {
            addItem: function (newItem) {
                myArray.push(newItem);
            },
            printItems: function () {
                console.log("lots if items");
            }
        };
    })();
    
    Api.addItem("Hello, world");
    Api.extensionValue = 5;
    
    我认为您应该清楚地描述什么是共享的,或“单例”数据,并将这些项目保持私有,就像我的示例中的myArray一样。

    看一看

    Object.freeze
    
    更多信息

    以下是Mozilla页面中的代码示例:

    var obj = {
      prop: function (){},
      foo: "bar"
    };
    
    // New properties may be added, existing properties may be changed or removed
    obj.foo = "baz";
    obj.lumpy = "woof";
    delete obj.prop;
    
    var o = Object.freeze(obj);
    
    assert(Object.isFrozen(obj) === true);
    
    // Now any changes will fail
    obj.foo = "quux"; // silently does nothing
    obj.quaxxor = "the friendly duck"; // silently doesn't add the property
    
    // ...and in strict mode such attempts will throw TypeErrors
    function fail(){
      "use strict";
      obj.foo = "sparky"; // throws a TypeError
      delete obj.quaxxor; // throws a TypeError
      obj.sparky = "arf"; // throws a TypeError
    }
    
    fail();
    
    // Attempted changes through Object.defineProperty will also throw
    Object.defineProperty(obj, "ohai", { value: 17 }); // throws a TypeError
    Object.defineProperty(obj, "foo", { value: "eit" }); // throws a TypeError
    
    然而,浏览器支持仍然是局部的


    编辑:请参阅Kernel James的答案,它与您的问题更相关(冻结将保护对象,但不保护重新分配对象。但是const将)但在浏览器支持有限的情况下也存在同样的问题。

    将其设置为
    常量

    const Api = "hi";
    
    Api = 0;
    
    alert(Api); //"hi"
    

    我不是JS大师,但我不认为单凭JS就可以做到这一点。也许看看微软的新“TypeScript”,它有更好的语言功能,可以编译成JS,也许这可以让你保护它。是的,我不认为有任何简单的方法可以避免第三方脚本(甚至你自己的脚本)对全局的冲击但我建议您为对象使用一个不太可能被其他脚本使用的名称
    var TFQ={}
    可能比
    Api
    更不容易发生冲突。您可以尝试以下方法:。也许会有帮助。。;。谢谢但是,小部件如何与主机通信?我如何“观察”Api.widgetsApi[“widget”]以获得新的“消息”?@JimmieLin:widgetsApi
    中的函数仍然可以与
    Api
    对象交互。因此,您可以调用其他函数并从中编辑变量。例如,如果您有
    Api.widgetApi.Debug.Messages.push()
    ,则可以将其链接到全局
    Api
    中的
    push
    函数。因此,从本质上讲,小部件中的
    Api.widgetApi.Debug.Messages.push()
    相当于它们之外的
    Api.Debug.Messages.push()
    ?听起来很酷,谢谢!只要在
    widgetApi
    中有一个函数调用它外部的函数(
    this.Debug.Messages.push()
    )就比Object.freeze好,这应该是公认的答案!显然,这保护了对象,但不是p