无论如何,是否可以让实例共享相同的函数,但同时具有私有变量?

发布于 2024-11-06 19:20:20 字数 615 浏览 3 评论 0原文

我有这段代码:

var Human=function(name){
  this._name=name;
};
Human.prototype.Shout=function(){
  alert(this._name);
};

var tom=new Human("tom");
var john=new Human("john");
alert(tom.Shout===john.Shout);

现在 ._name 不是“私有”。我想将 ._name 设置为“私有”,但同时我不希望为 Human 的每个实例创建附加函数(换句话说 tom.Shout 必须 === 到 john.Shout),因为为每个实例都是很好的..不必要的(好吧,题外话 - 我们可以在另一个线程上讨论这个问题)

我的结论是我想要实现的目标(让 ._name 是“私有的”,同时让 tom. Shout===john.Shout)是不可能的。

但我只是想在得出任何结论之前有 200% 的把握。

(只要满足要求,我欢迎任何黑客,即不为每个实例创建附加函数)

如果我们必须创建附加函数来进行范围界定,那很好,但该数字应该是固定数字,并且该数字不应随着每个额外的 Human 实例。

I have this piece of code:

var Human=function(name){
  this._name=name;
};
Human.prototype.Shout=function(){
  alert(this._name);
};

var tom=new Human("tom");
var john=new Human("john");
alert(tom.Shout===john.Shout);

Right now ._name is not "private". I want to make ._name "private", but at the same time i do not wish to create additional functions for each instance of Human (in other words tom.Shout Must be === to john.Shout) because creating additional functions for each instance is just well.. unnecessary (ok offtopic - we can debate this on another thread)

My conclusion is that what I'm trying to achieve (having ._name be "private" and at the same time having tom.Shout===john.Shout) is impossible.

But I just want to be 200% sure before jumping into any conclusions.

(I welcome any hacks as long as the requirements are met, i.e no creating of additional functions for each instance)

If we have to create additional functions to do scoping that's fine but that number should be a fixed number and that number should not increase with each additional instance of Human.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

嘿哥们儿 2024-11-13 19:20:20

更新

您要查找的@name 这是一个实例变量。祈祷它在 es.next 中,但我们还没有。也许两年后。

如果您关心干净的 API,那么这里是您的解决方案:

function Class(foo) {
    Class.priv(this).foo = foo;
}

Class.priv = (function() {
    var cache = [],
        uid = 1;

    return function(obj) {
        if (!this.__id) {
            this.__id = uid;
            cache[uid++] = {};
        }
        return cache[this.__id];
    };

}());

Class.prototype.bar = function() {
    console.log(Class.priv(this).foo);
}

将所有数据作为构造函数的函数存储在缓存中。对象上没有杂乱的数据。

原创

然而,不存在“私人”这样的东西。

您所能做的就是在函数内创建一个局部变量。

构造函数

var Human = function(name) {
    // local variable.
    var _name = name;
}

有一个局部变量,根据局部定义,该变量在构造函数之外不可用。

这意味着您无法像原型一样通过外部代码访问它。

然而,你可以做的是使用 ES5 使其只读。

var Human = function(name) {
    Object.defineProperty(this, "name", { value: name });
}

如果你能真正实现你的要求,你将在 js 方面取得巨大突破。我已经尝试这样做了好几个小时。

另一种模式是:

var Human = function(name) {
   this.name = name;

   return {
       Shout: this.Shout.bind(this)
   };
}

Human.prototype.Shout = function() {
   console.log(this.name);
}

这会产生调用 .bind 并为每个实例创建新对象的开销。

Update

Your looking for @name which is an instance variable. Pray it's in es.next, but we don't have it yet. Maybe in two years.

If you care about a clean API then here is your solution:

function Class(foo) {
    Class.priv(this).foo = foo;
}

Class.priv = (function() {
    var cache = [],
        uid = 1;

    return function(obj) {
        if (!this.__id) {
            this.__id = uid;
            cache[uid++] = {};
        }
        return cache[this.__id];
    };

}());

Class.prototype.bar = function() {
    console.log(Class.priv(this).foo);
}

Store all the data in a cache as a function of the constructor. No data is cluttered on the object.

Original

However there is no such thing as "private".

All you can do is create a local variable inside a function.

The constructor function

var Human = function(name) {
    // local variable.
    var _name = name;
}

Has a local variable that by very definition of being local is not usable outside of the constructor function.

This means that you cannot access it in external code like the prototype.

What you can do however is make it read only using ES5

var Human = function(name) {
    Object.defineProperty(this, "name", { value: name });
}

If you can truly achieve what your asking, you'd make a huge breakthrough in js. I've attempted to do just that for many hours.

A different pattern would be :

var Human = function(name) {
   this.name = name;

   return {
       Shout: this.Shout.bind(this)
   };
}

Human.prototype.Shout = function() {
   console.log(this.name);
}

This has the overhead of calling .bind and creating a new object for every instance though.

黎夕旧梦 2024-11-13 19:20:20

这个怎么样?

    var Human = function (name) {
        var _name = name;

        this.getName = function () {
            return _name;
        }
    };
    Human.prototype.Shout = function () {
        alert(this.getName());
    };

    var tom = new Human("tom");
    var john = new Human("john");

    tom.Shout(); // tom
    john.Shout(); // john
    alert(tom.Shout === john.Shout); // true

编辑:
前者为 GET 属性创建另一个函数,
如果不创建附加功能,这是不可能的。

how about this ?

    var Human = function (name) {
        var _name = name;

        this.getName = function () {
            return _name;
        }
    };
    Human.prototype.Shout = function () {
        alert(this.getName());
    };

    var tom = new Human("tom");
    var john = new Human("john");

    tom.Shout(); // tom
    john.Shout(); // john
    alert(tom.Shout === john.Shout); // true

EDIT:
the former creates another function for GET property,
it is not possible without creating additional functions.

巡山小妖精 2024-11-13 19:20:20

读过这个问题,不明白,因为 this._name 只是不是私有的,所以这个问题有点奇怪。这就是在我的测试中原型方法添加一次并可供所有实例使用的方式。我再说一遍:this._name 这里不是私有的。如果添加局部变量,并希望通过原型方法中的闭包访问它,则调用局部变量的值将导致所有实例得到相同的值。

不管怎样,通过这个构造函数,this._name getter 和shout 方法被添加到原型链一次,从而可用于Human 的所有实例。

function Human(name) {
    if (!(this instanceof Human)){
        return new Human(name);
    }
    this._name = name;

    if (!Human.prototype.Name){
         Human.prototype.Name = function(val){
            if (val){
               this._name = val;
               return this;
            }
            return this._name;
          };
          Human.prototype.shout = function(){
              alert(this._name);
          }
    }
}

Did read the question, didn't understand, because this._name is just not private, so the question is a bit weird. This is how in my test the prototype methods are added once and available to all instances. I repeat: this._name is not private here. If you add a local variable, and want to access it via a closure in a prototype method, calling the value of the local variable will result in the same value for all instances.

Anyway, with this constructor function the this._name getter and shout methods are added to the prototype chain once and thereby available for all instances of Human.

function Human(name) {
    if (!(this instanceof Human)){
        return new Human(name);
    }
    this._name = name;

    if (!Human.prototype.Name){
         Human.prototype.Name = function(val){
            if (val){
               this._name = val;
               return this;
            }
            return this._name;
          };
          Human.prototype.shout = function(){
              alert(this._name);
          }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文