JavaScript对象内部的私有变量定义

JavaScript对象内部的私有变量定义,javascript,jquery,class,constructor,prototype,Javascript,Jquery,Class,Constructor,Prototype,我正在学习使用prototype属性在JavaScript上定义“类”函数。 当我像这样定义一个People类时,一切都很好: var People = function(firstName, lastName){ // public this.firstName = firstName; this.lastName = lastName; this.fullName = function(){ console.log(full_name);

我正在学习使用prototype属性在JavaScript上定义“类”函数。 当我像这样定义一个
People
类时,一切都很好:

var People = function(firstName, lastName){
    // public
    this.firstName = firstName;
    this.lastName  = lastName;

    this.fullName = function(){
        console.log(full_name);
        return this;
    };

    // private
    var self = this;
    var full_name = function(){
        return self.firstName + ' ' + self.lastName;
    }();
};

var person = new People('John', 'Smith');
person.fullName();  // => "John Smith"
但是,当我将
fullName
方法移出初始定义时,如下所示:

var People = function(firstName, lastName){
    // public
    this.firstName = firstName;
    this.lastName  = lastName;

    // private
    var self = this;
    var full_name = function(){
        return self.firstName + ' ' + self.lastName;
    }();
};

People.prototype.fullName = function(){
    console.log(full_name);
    return this;
};

var person = new People('John', 'Smith');
person.fullName();  // => "ReferenceError: full_name is not defined"
我有个错误。我不明白为什么…?

这里:

var full_name = function(){
    return self.firstName + ' ' + self.lastName;
}();
您正在将变量“full_name”设置为调用该匿名函数的结果。不过,它只是在该构造函数的上下文中声明的一个变量,所以这并不重要;构造函数之外的任何东西都无法访问它

因此,在原型函数中,您会得到一个错误,因为“全名”实际上没有定义。如果您想在原型上使用全名函数,只需在那里声明它:

People.prototype.fullName = function() {
  return this.firstName + " " + this.lastName;
};
如果您想要一个只能由构造函数中的代码访问的“私有”函数,那么您可以执行以下操作:

var People = function(firstName, lastName){
    // public
    this.firstName = firstName;
    this.lastName  = lastName;

    // private
    var self = this;
    function fullName(){
        return self.firstName + ' ' + self.lastName;
    }

    this.addressMe = function(msg) {
        return fullName() + ": " + msg;
    };
};
然后你可以做:

var bob = new People("Bob", "Scum");
alert( bob.addressMe("stand and deliver") ); // "Bob Scum: stand and deliver"
在这里:

您正在将变量“full_name”设置为调用该匿名函数的结果。不过,它只是在该构造函数的上下文中声明的一个变量,所以这并不重要;构造函数之外的任何东西都无法访问它

因此,在原型函数中,您会得到一个错误,因为“全名”实际上没有定义。如果您想在原型上使用全名函数,只需在那里声明它:

People.prototype.fullName = function() {
  return this.firstName + " " + this.lastName;
};
如果您想要一个只能由构造函数中的代码访问的“私有”函数,那么您可以执行以下操作:

var People = function(firstName, lastName){
    // public
    this.firstName = firstName;
    this.lastName  = lastName;

    // private
    var self = this;
    function fullName(){
        return self.firstName + ' ' + self.lastName;
    }

    this.addressMe = function(msg) {
        return fullName() + ": " + msg;
    };
};
然后你可以做:

var bob = new People("Bob", "Scum");
alert( bob.addressMe("stand and deliver") ); // "Bob Scum: stand and deliver"

Pointy对privateshared成员使用了错误的模式,该模式用于private实例特定的成员,每个实例都有自己的addressMe函数

私有共享成员的模式可以将原型封装在IIFE中:

var People = function(firstName, lastName){
    // public
    this.firstName = firstName;
    this.lastName  = lastName;
};

(function(){
  // private shared member
  var full_name = function(){
      return this.firstName + ' ' + this.lastName;
  };
  //privileged member that has access to private shared
  //  fullName is a closure and full_name is available
  //  in the colosure scope created for this function
  People.prototype.fullName = function(){
    //calling private member, make sure you set
    //  the invoking object (this) by using
    //  Function.prototype.call
    console.log(full_name.call(this));
    return this;
  };
}());

var person = new People('John', 'Smith');
person.fullName();
不能将此模式用于特定于实例的私有成员,但函数full_name不是特定于实例的


可以找到受保护的模式以及有关原型和构造函数的更多信息。

Pointy对私有共享成员使用了错误的模式,该模式适用于私有特定于实例的成员,每个实例都有自己的addressMe函数

私有共享成员的模式可以将原型封装在IIFE中:

var People = function(firstName, lastName){
    // public
    this.firstName = firstName;
    this.lastName  = lastName;
};

(function(){
  // private shared member
  var full_name = function(){
      return this.firstName + ' ' + this.lastName;
  };
  //privileged member that has access to private shared
  //  fullName is a closure and full_name is available
  //  in the colosure scope created for this function
  People.prototype.fullName = function(){
    //calling private member, make sure you set
    //  the invoking object (this) by using
    //  Function.prototype.call
    console.log(full_name.call(this));
    return this;
  };
}());

var person = new People('John', 'Smith');
person.fullName();
不能将此模式用于特定于实例的私有成员,但函数full_name不是特定于实例的


可以找到受保护的模式以及有关原型和构造函数的更多信息。

没有类或私有,它是函数和作用域,但一些smartypants决定将其称为“类”和“私有/公共”(可能是Crockford,让我们责备他)。不清楚您想要什么。如果您希望“full_name”是作为原型属性可见的函数,那么就没有理由将其设置为“private”。@adeneo您是对的。。。这就是为什么我称它为“类式”的原因,lolsee也对@Bergi做了很好的解释,但这不是我在这里问的问题。没有类或私有,它是函数和范围,但一些smartypants决定称它为“类”和“私有/公共”(可能是Crockford,让我们责备他)。不清楚你想要什么。如果您希望“full_name”是作为原型属性可见的函数,那么就没有理由将其设置为“private”。@adeneo您是对的。。。这就是为什么我称之为“类式”的原因,lolsee也对@Bergi做了很好的解释,但这不是我在这里问的问题。你对私有共享成员使用了错误的模式。您使用的模式是专用于私有实例的(每个实例都是唯一的)。因为全名是一个函数,可以共享,所以您不必放弃原型来实现它。@HMR我同意;我可能不会编写这样的代码。原始问题的意图并不十分清楚。您对私有共享成员使用了错误的模式。您使用的模式是专用于私有实例的(每个实例都是唯一的)。因为全名是一个函数,可以共享,所以您不必放弃原型来实现它。@HMR我同意;我可能不会编写这样的代码。原始问题的意图并不十分清楚。谢谢你的回答,但更多的是你在最后附加的链接。很好的解释!!!你也有自己的博客吗?@Lior谢谢你,没有博客。我认为JavaScript原型是编程中最容易被误解的东西之一,我自己在试图弄明白它的时候就写了这篇文章。因此,这是完美的,因为我希望评论会指出错误或建议改进。Thx为您的答案,但更多为您在它的结尾附加的链接。很好的解释!!!你也有自己的博客吗?@Lior谢谢你,没有博客。我认为JavaScript原型是编程中最容易被误解的东西之一,我自己在试图弄明白它的时候就写了这篇文章。所以这是完美的,因为我希望评论会指出错误或提出改进建议。