删除对对象方法的公共访问
我想获取一个对象并从中删除一些方法。
即我内部有一个带有 getter/setter 的对象,并且我想让外部用户访问它。我不希望他们有权访问设置器功能。
我不想通过删除原始对象引用来更改原始对象引用,而是创建一个指向同一对象但具有较少方法的新对象引用。
- 我该怎么做呢?
- 这是一种设计模式吗?
- 对于此类问题是否有众所周知的解决方案?
我有这个功能的实现
var readOnly = function(obj, publicData) {
// create a new object so that obj isn't effected
var object = new obj.constructor;
// remove all its public keys
_.each(object, function(val, key) {
delete object[key];
});
// bind all references to obj
_.bindAll(obj);
// for each public method give access to it
_.each(publicData, function(val) {
object[val] = obj[val];
});
return object;
};
对于所有预期目的,返回的对象应该与原始对象相同,除了某些方法不再存在。内部 this
引用不应在任何函数中中断。原型链不应该断裂。
- 这样的函数的直观名称是什么?
- 我当前的实施是否存在任何我应该注意的陷阱?
I would like to take an object and remove some methods from it.
i.e. I have internally have an object with getter/setters on it and I want to give external users access to it. I don't want them to have access to the setter functions.
I don't want to change original object reference by removing methods from it but create a new object reference that points to the same object but has less methods on it.
- How would I go about doing this?
- Is this a design-pattern?
- Are there well known solutions for these kinds of problems?
I have an implementation of this function
var readOnly = function(obj, publicData) {
// create a new object so that obj isn't effected
var object = new obj.constructor;
// remove all its public keys
_.each(object, function(val, key) {
delete object[key];
});
// bind all references to obj
_.bindAll(obj);
// for each public method give access to it
_.each(publicData, function(val) {
object[val] = obj[val];
});
return object;
};
See live example, _.each
_.bindAll
For all intended purposes the object returned should be the same as the original object except some of the methods aren't there anymore. The internal this
reference should not break in any of the functions. The prototype chains should not break.
- What would be an intuitive name for such a function?
- Are there any pitfalls with my current implementation that I should be aware of?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
你应该做的是使用外观模式,它只包含你想要保留的方法和委托模式将这些方法委托给原始对象的实例。借助 Javascript 提供的丰富反射,您应该能够相当轻松地以编程方式生成这些外观。
What you should do is use a Facade Pattern that only has the methods you want to keep and Delegation Pattern to delegate those methods to an instance of the original object. With the rich reflection that is available with Javascript you should be able to generate these Facades programmaticlly fairly easily.
您的实现至少有一个问题是对 obj.constructor 的依赖。众所周知,
constructor
属性不是只读的,而且很容易搞乱。考虑以下模式,这是在 Javascript 中定义类的一种非常常见的方法:我认为执行此操作的方法是以您的 obj 实例作为原型创建一个新类。然后,您可以通过在新类的对象上添加空键来阻止对旧函数的访问:(
这部分基于 Crockford 的强大构造函数,此处讨论。)
编辑:我更新了上面的代码以解决您的评论。它现在看起来与您的实现有些相似,但它更简单并且避免了
构造函数
问题。正如您所看到的,对公共函数的引用现在引用旧对象。At least one issue with your implementation is the reliance on
obj.constructor
. Theconstructor
property is notoriously not read-only, and can be easily messed up. Consider the following pattern, which is a pretty common way to define classes in Javascript:I think the way to do this is to create a new class with your
obj
instance as the prototype. You can then block access to the old functions by adding empty keys on an object of the new class:(This is partially based on Crockford's power constructor functions, discussed here.)
EDIT: I updated the code above to address your comments. It now looks somewhat similar to your implementation, but it's simpler and avoids the
constructor
issue. As you can see, references to in public functions now refer to the old object.如果你想让
instanceof
工作,我们需要使用继承,就像 @nrabinowitz 的解决方案。在该解决方案中,不需要的方法被隐藏,键设置为空,并且这些键可供用户访问,因此用户可能会重置它们。我们可以通过将这些键隐藏在中间对象中来防止这种情况,并且因为它是从中间类实例化的,所以继承不会中断。在以下示例中,
i
和j
表示实现成员值的两种方法。一个是闭包中的私有成员,另一个是类的公共成员。正如您所看到的,所有setter和reduce方法都隐藏在受限对象中。用户只能使用getter或增加
i
和j
的值。If you want
instanceof
works, we need to use inheritance, like @nrabinowitz's solution. In that solution, unwanted methods are hidden with keys set to null, and those keys are accessible to user so they might be reset by user. We can prevent this by hiding those keys in an intermediate object, and because it's instantiated from an intermediate class so inheritance won't break.In the following example,
i
andj
represent two ways to implement member values. One is private member in closure and the other is public member of the class.As you can see, all setters and decrease methods are hidden in the restricted object. User can only use getter or increase the value of
i
andj
.如果您想要做的只是将对象中的某些方法公开为公共,并将其余方法保留为私有,您可以执行类似以下操作(在下面的示例中,privateMethod2 永远不会在返回给用户的新“只读”对象中显示):
If all you want to do is expose certain methods in your object as public and keep the rest private, you can do something like this (in the example below privateMethod2 is never revealed in the new "read only" object returned to the user):
您正在寻找的称为 JavaScript 中的模块模式。它与 Gobhi 所描述的非常接近,但通常它是一个自执行函数。
详细信息可以在这里找到:
http://yuiblog.com/blog/2007/ 06/12/module-pattern/
和:
http ://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
What you are looking for is called the module pattern in JavaScript. It's pretty close to what Gobhi describes but generally it is a self executing function.
Details can be found here :
http://yuiblog.com/blog/2007/06/12/module-pattern/
and :
http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
您正在选择非常复杂的方法。首先提供更多细节:
对评论 1 的回应:
更多关于 Closure 编译器混淆工作的信息。
Google 使用以下方法(GMaps、GMail 等)。
You are choosing very complicated approach. Provide more details first:
Response to comment 1:
A little bit more about Closure compiler obfuscation works.
The following method is used by Google (GMaps, GMail and etc.).
我认为 @nrabinowitz 的
getRestricted
(link) 函数几乎就是您正在寻找的答案。我不太热衷于将 GOF 模式应用到 JavaScript(本身就有一个完整的讨论)。但这对我来说就像一个 装饰器 因为我们正在改变某些对象的运行时行为 - 但是反过来 - 如果你喜欢的话,可以使用 De-Decorator :)
I thought @nrabinowitz's
getRestricted
(link) function was pretty much the answer you were looking for.I'm not a big fan of GOF pattern application to JavaScript (there's a whole discussion in itself). But this smells to me like a Decorator since we're changing runtime behaviour on certain objects - but in reverse - a De-Decorator if you like :)
或许:
maybe:
我想说,与您的情况非常匹配的模式是代理。
更新:正如注释所示,代理应该支持与真实对象相同的接口,因此与问题中所述的问题不太匹配。在关于代理的维基百科文章的底部,我找到了一篇有趣文章的链接,该文章比较了 代理、适配器和外观模式。
I'd say that the pattern that matches your situation quite closely is the Proxy.
UPDATE: As the comments indicate, a Proxy should support the same interface as the real object and therefore is not a good match to the problem stated in the question. At the bottom of the wikipedia article on Proxy I found a link to an interesting article that compares Proxy, Adapter and Facade patterns.