防止覆盖 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 方法来防止它。只需将 writable 和 configurable 属性设置为 false。你可以找到更多关于here的信息
在你的情况下,它应该是这样的:
var $ = (function()
var newObject = ;
Object.defineProperty (newObject, "function1", value: function() alert("this is Function1");, writable:false, configurable:false);
// etc.
return object;
());
请注意,将 writable 和 configurable 属性设置为 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 函数的主要内容,如果未能解决你的问题,请参考以下文章