JavaScript对象中的私有变量定义

时间:2014-05-01 21:49:55

标签: javascript jquery class constructor prototype

我正在学习使用prototype属性在JavaScript上定义'class like'函数。 当我像这样定义一个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"

我收到了一个错误。我不明白为什么...... ??

2 个答案:

答案 0 :(得分:3)

下面:

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

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

因此,在该原型函数中,您会收到错误,因为“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"

答案 1 :(得分:1)

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不是特定于实例的。

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