您是否可以用一个也可以访问这些私有属性的函数来扩展一个可以访问私有属性的对象?

Can you extend an object that has access to private properties with a function that can also access those private properties?

本文关键字:一个 属性 访问 扩展 对象 函数 是否 也可以      更新时间:2023-09-26

我正在创建一个框内的对象。在这个附件中还有对象的函数可以访问的私有属性——这是预期的。

我的问题:我希望其他人能够用他们自己的函数(来自不同上下文的函数)扩展我的对象,但是这些函数也需要访问相同的私有属性——我还没有找到一种方法来实现这一点。

我已经尝试了各种配置。call,也包装他们的功能在一个新的功能,除其他事项。我觉得我已经接近解决办法了,但还差得远。

下面是一段简化的示例代码,它准确地反映了我的情况:

//extension object
//fn2 can be any function, with any number of arguments, etc.
var obj1 = {};
obj1.fn2 = function (s1, s2){ console.log(priv); };
//actual object
var obj2 = (function (){
    //private property
    var priv = "hello world";
    //return object
    var obj3 = {};
    //return object's native fn (works)
    obj3.fn = function (s){ console.log(priv); };
    //extension happens here - but is obviously not correct
    obj3.fn2 = obj1.fn2;
    //return object
    return obj3;
})();
//try output
obj2.fn("goodbye world"); //works
obj2.fn2("goodbye world", "thx 4 teh phish"); //fails

如有任何见解将不胜感激。如果我想要的是不可能的,我完全理解,但它似乎应该是:P

编辑:感谢大家的回复。我完全理解,作为公共属性更容易访问,并且通常继承的对象将无法访问它们。然而,由于新函数被附加到原始对象上,我不得不相信有一种方法可以使用原始上下文,而不是创建新函数的上下文。

现在,我是第一个说eval是邪恶的人——事实上,我从来没有使用过它,甚至从来没有考虑过使用它。然而,我正在尝试一切我能想到的工作-我偶然发现了这个(看似)工作的解决方案:

obj3。fn2 = eval(obj1.fn2.toString());

如果我检查以确保obj1。Fn2是一个typeof函数,这会对我的代码造成伤害吗?它没有执行函数,所以我看不出是怎么回事,但也许我遗漏了什么?

Javascript没有"受保护"的类比。要么超级私有,要么完全公开。从这里你可以选择:

  1. 重新考虑你的类设计,让子类只依赖于父类的公共接口

  2. 在公共接口中添加getter和setter函数。虽然不一定是最好的事情,但您不妨将属性公开(除了最佳实践问题和诸如此类的)

  3. 使用公共属性代替。这是在Javascript中进行OO继承的"自然"方式,如果使用诸如在名称开头添加下划线之类的捐赠方式,通常不会出现问题。作为奖励,您可以使用原型继承特性(知道如何使用它而不是只使用基于闭包的类是很好的)

    function Base(){
        this._priv = "Hello world"
    };
    Base.prototype = {
        fn: function(){
            console.log(this._priv);
        }
    }
    var obj2 = new Base();
    obj2.fn = function(){ ... }
    

我不想回答我自己的问题——似乎有点失礼——但这就是生活。(因为我今天醒来是法国人?)

所以,虽然我发现eval()解决方案我昨晚在编辑我的原始问题似乎是一个有效的解决方案,并正确使用eval来保留对象的上下文在新函数中,它远非完美。

首先,它在FF中工作,但IE和Chrome似乎都讨厌它(这些是我尝试的下一个,我放弃尝试其他人后,他们都失败了)。虽然我确信可能可以跨浏览器工作,但这似乎很麻烦。

其次,它确实给了新函数相当多的功能,当我看我的代码更多的时候,我确实喜欢控制这些新函数被添加到我的对象的访问权限的想法。

第三,.eval()通常很慢,而.apply()(通常更快)可能工作得足够好。

这是因为我昨晚意识到这个对象上的任何新函数都不需要设置任何私有变量(至少,我相当确定它们不会)-并且.apply()可以很好地传递值以供它们读取。

我相信还有更多的事情要做,而不仅仅是这3件事,但现在我想我要用更多的"包装"解决方案-像这样:

var f = function (){
    var fauxThis = {};
    fauxThis.priv = priv;
    obj1.fn2.apply(fauxThis, arguments);
};
obj3.fn2 = f;
//(To be placed where I had "obj3.fn2 = obj1.fn2;")

我现在当然愿意考虑在非常具体的情况下使用eval()——甚至可能在我最终决定采取哪个方向之前重新审视它的具体用法。(特别是如果我能想到需要设置私有值的情况)

谢谢大家的意见!

最快和最简单的解决方案是在任何所谓的私有属性前加上下划线(_)。

我个人喜欢把我的私有属性装入一个单独的对象中,这个对象将被放置在对象上,像这样:

obj.publicProp = 20;
obj._.privateProp = true;

我不会担心这么多,下划线基本上是私有的通用符号,所以那些使用脚本的人会知道它是私有的,不应该被触摸。或者,更好的是,把它从公共文档中删除;)

您可以使用其他方法来模拟"真正的"受保护变量,但它们不是最好的,因为它们避免了垃圾收集,并且使用起来很笨拙。