防止覆盖 Javascript 函数

Posted

技术标签:

【中文标题】防止覆盖 Javascript 函数【英文标题】:Prevent Overriding Javascript Function 【发布时间】:2017-05-29 02:44:23 【问题描述】:

我在 javascript 中使用模块化模式。我想知道我们是否可以防止公共模块被覆盖。 比如下面的代码中function1、function2、function3和function4可以在外面访问但是我不想覆盖。如果这些函数被覆盖,那么我希望编译器生成错误消息

"use strict";

var $ = (function()
return
      function1 : function()
          alert("this is Function1");
      ,
      function2 : function()
          alert("this is Function2");
      ,
      function3 : function()
          alert("this is Function3");
      ,
      function4 : function()
          alert("this is Function4");
      
    ;
());


$.function1(); //will alert - this is Function1
$.function2(); //will alert - this is Function2

/* 
  I don't want to do this, If I do, then I want the compiler to generate an   
  error message
*/
$.function3=function()
    alert('function 3 is overridden');

;
$.function3(); //will alert - function 3 is overridden

【问题讨论】:

在 SO 上对此问题进行更深入的讨论:***.com/questions/366047/… 【参考方案1】:

使用Object.defineProperty,您可以将该属性声明为只读。

// Make sure an error is thrown when attempting to overwrite it
// Without strict-mode, re-assigning will fail silently
'use strict';

var API = ;
Object.defineProperty(API, 'function1', 
  writable: false,
  value: function() 
    console.log('Called function1');
  
);

API.function1();
API.function1 = null;

【讨论】:

有错别字,可写, @weiyaou 已修复。谢谢【参考方案2】:

是的,可以通过使用 Object.defineProperty 方法来防止它。只需将 writableconfigurable 属性设置为 false。你可以找到更多关于here的信息

在你的情况下,它应该是这样的:

var $ = (function()

var newObject = ;

Object.defineProperty (newObject, "function1", value: function()   alert("this is Function1");, writable:false, configurable:false);

// etc.

return object;
());

请注意,将 writableconfigurable 属性设置为 false 只会防止 function1 属性被覆盖。但是,由于 JavaScript 中的每个函数都是 Function 对象,因此该函数对象不受 writable:false 的保护。因此,例如,function1 的原型仍然可以更改。

如果你想完全避免以任何方式修改你的函数,你应该使用 Object.freeze 方法。请阅读this 非常有用的文章。

【讨论】:

这是 Object.freeze 方法的兼容性表:kangax.github.io/compat-table/es5/#test-Object.freeze,这是 Objact.defineProperty 的表:kangax.github.io/compat-table/es5/#test-Object.defineProperty。这些表是相同的。【参考方案3】:

您可以使用Object.freeze(obj) 将整个返回的对象设置为不可变。此外,请注意,您可以使用const 而不是var 来避免重新分配对象。

'use strict';

const $ = (function() 
  return Object.freeze(
    function1: function() 
      alert('this is Function1');
    ,
    function2: function() 
      alert('this is Function2');
    ,
    function3: function() 
      alert('this is Function3');
    ,
    function4: function() 
      alert('this is Function4');
    
  );
)();


$.function1(); //will alert - this is Function1
$.function2(); //will alert - this is Function2

// This will now error
$.function3 = function() 
  alert('function 3 is overridden');
;
$.function3(); // will not run

【讨论】:

太棒了,谢谢!这就是我需要的。 还有一个问题。当我尝试编写这样的代码时,它仍然会覆盖该函数(通过使用匿名函数)。当我运行它时,它会显示警报,然后只有它会给出错误消息“未捕获的类型错误:无法分配给只读属性”。后来当我尝试调用该函数时,由于匿名覆盖函数,它根本不起作用。 $.function3=(function() alert('function 3 is overridden'); ()); @greencheese 你的例子是一个自调用函数/IIFE。覆盖实际上并没有成功,但该函数确实在错误发生之前运行。看看这是否有助于理解:jsfiddle.net/0oku2tah/1 @greencheese 如果您想在编译时捕获此类错误,则需要在开发过程中运行第三方类型检查器。这将不会阻止使用您的代码的人修改它。【参考方案4】:

有几种方法可以做到这一点。如果要在覆盖时处理消息,可以使用getter和setter:

var $ = (function()
  var obj = 
      function1 : function()
          alert("this is Function1");
      ,
      function2 : function()
          alert("this is Function2");
      ,
      get function3() 
      	  alert("this is Function3");
      ,
      set function3(value) 
      	  console.warn('You cannot override this function');
      ,
      function4 : function()
          alert("this is Function4");
      
  ;
  
  return obj
());

// throw warning
$.function3 = 'foo';

由于您使用的是 IIFE,因此您可以在属性内容之外定义源并引用它。

ES6 语法示例:

let $ = (function () 
  let func3 = function () 
    alert('this is Function3');
  ;

  class $ 
    static set function3(value) 
      return func3;
    
    static get function3() 
      return func3;
    
  
  
  return $;
());

$.function3 = 'foo';
$.function3();

【讨论】:

以上是关于防止覆盖 Javascript 函数的主要内容,如果未能解决你的问题,请参考以下文章

是否可以防止 C 共享库中的函数覆盖?

学习Javascript

防止在Julia并行化中覆盖模块

前端入门12-JavaScript语法之函数

防止多次执行 JavaScript 函数

如果条目已存在,如何防止覆盖 DynamoDB 项目