15

我试图更深入地掌握原型继承和类创建(我知道,还有其他方法,但为此我试图掌握原型。)我的问题是:使用下面的代码示例,是有一种方法可以在内部创建私有变量,Tree并且Fruit不会与函数一起返回,但原型函数仍然可以访问genusbulk

var Tree = function ( name, size ) { 
    this.name = name;
    this.size = size;
};

Tree.prototype.genus = function(){
    return ((typeof this.name !== 'undefined') ? this.name : 'Hybridicus Maximus');
};
Tree.prototype.bulk = function(){
    return ((typeof this.size !== 'undefined') ? this.size : '8') + ' ft';
};


var Fruit = function( name, size ) { 
    this.name = name;
    this.size = size;
};

Fruit.prototype = new Tree();
// Fruit.prototype = Tree.prototype; -- I know this can be used, too.

Fruit.prototype.bulk =  function(){
    return ((typeof this.size !== 'undefined') ? Math.floor(this.size / 2) : '4') + ' lbs';
};

var pine = new Tree('Pine', 9);
var apple = new Fruit('Apple', 6);

console.log(pine.genus(), pine.bulk()); // Outputs: "Pine 9 ft"
console.log(apple.genus(), apple.bulk()); // Outputs: "Apple 3 lbs"

编辑:我正在尝试用可以在原型函数中访问的私有变量替换this.name和。this.size很抱歉没有说清楚!

4

4 回答 4

14

是的。你可以这样做:

(function() {
  var private = "hi";

  Tree.prototype.genus = function(){
    return ((typeof this.name !== 'undefined') ? this.name : 'Hybridicus Maximus');
  };
  Tree.prototype.bulk = function(){
    return ((typeof this.size !== 'undefined') ? this.size : '8') + ' ft';
  };
})();

现在,这将提供一个这些函数可以看到的私有变量,但它将是一个私有“类”变量——换句话说,所有实例都将共享同一个变量。如果您希望每个实例都有一个私有变量,则必须在构造函数(或“init”方法或其他任何方法)中执行此操作,这意味着也必须在那里创建共享这些私有变量的方法。(您当然可以在原型上放置一个函数,该函数将在构造时创建实例方法。)

编辑——你可以做的一件事是使用这样的技术来构建一个像 jQuery 的“.data()”这样的机制,这样你就有一个类变量作为保存每个实例值的地方。这会有点笨拙,但它是可行的。

于 2011-06-10T14:35:46.423 回答
2

这就是我在一篇关于JavaScript 中的类、私有成员和原型继承的博客文章中所写的内容。基本上,您想创建一个对每个对象都唯一的私有变量访问器函数,然后让这些原型方法调用该私有访问器函数,并为其提供仅在闭包中可用的密钥:

(function(_) {
  Tree = function ( name, size ) { 
    var hidden = {
      name: name,
      size: size
    };
    this._ = function($) {
      return _ === $ && hidden;
    };
  };

  Tree.prototype.genus = function(){
    return ((typeof this._(_).name !== 'undefined') ? this._(_).name : 'Hybridicus Maximus');
  };
  Tree.prototype.bulk = function(){
    return ((typeof this._(_).size !== 'undefined') ? this._(_).size : '8') + ' ft';
  };

  Fruit = function( name, size ) { 
    Tree.apply(this, arguments);
  };
  Fruit.prototype = new Tree();
  // Fruit.prototype = Tree.prototype; -- I know this can be used, too.

  Fruit.prototype.bulk =  function(){
    return ((typeof this._(_).size !== 'undefined') ? Math.floor(this._(_).size / 2) : '4') + ' lbs';
  };
})({});



var pine = new Tree('Pine', 9);
var apple = new Fruit('Apple', 6);

console.log(pine.genus(), pine.bulk()); // Outputs: "Pine 9 ft"
console.log(apple.genus(), apple.bulk()); // Outputs: "Apple 3 lbs"

console.log(pine._(), pine._({})); // Outputs: "false false" because outside of closure

你会注意到最后一行显示私有变量在闭包之外是不可访问的,因此第三方代码无法检索到,除非由访问器函数提供。

于 2013-02-07T20:30:49.283 回答
0

可以这样轻松实现

function SharedPrivate(){
  var private = "secret";
  this.constructor.prototype.getP = function(){return private}
  this.constructor.prototype.setP = function(v){ private = v;}
}

var o1 = new SharedPrivate();
var o2 = new SharedPrivate();

console.log(o1.getP()); // secret
console.log(o2.getP()); // secret
o1.setP("Pentax Full Frame K1 is on sale..!");
console.log(o1.getP()); // Pentax Full Frame K1 is on sale..!
console.log(o2.getP()); // Pentax Full Frame K1 is on sale..!
o2.setP("And it's only for $1,795._");
console.log(o1.getP()); // And it's only for $1,795._

显然,关键点是通过使用闭包创建到私有变量的访问路径,然后在要创建的对象之间共享该访问点。使用接入点作为自然共享对象的原型是理想的情况。因此,通过使用工厂模式可以实现相同的功能Object.create(),如下所示;

function SharedPrivate(){
var priv = "secret";
return {gp : function(){return priv},
        sp : function(v){priv = v}
       }
}
sharedProto = SharedPrivate(); // priv is now under closure to be shared
var p1 = Object.create(sharedProto); // sharedProto becomes o1.__proto__
var p2 = Object.create(sharedProto); // sharedProto becomes o2.__proto__

JavaScript 原型结构是金..!

于 2016-03-06T11:56:55.530 回答
-1

我是根据您的问题标题而不是您提供的内容来编造这个的。我在这里有同样的问题。

var Tree = function(){

    var outprivatename = "bigsecret"

    var Tre = function(nickname){
        var privatename = "secret that no one should know" 
        this.nickname = nickname
        outprivatename = outprivatename + "-->" + nickname
        this.deepsecret=function(){return privatename + "---" + nickname}
    }

    Tre.prototype.getname=function(){
        console.log(outprivatename+'-----'+this.nickname)
        // console.log(privatename)
      return this.nickname
    }
    return Tre

}
//case one: each has unique closure; `outprivatename` is different for them
var pine = new (Tree())('pine')
var apple = new (Tree())('apple')
pine.getname() //bigsecret-->pine-----pine
apple.getname() //bigsecret-->apple-----apple
console.log(pine.deepsecret()) //secret that no one should know---pine
console.log(apple.deepsecret()) //secret that no one should know---apple

//case one: two share one closure; `outprivatename` is same for both
var Hybrid = Tree()
var hybrid1 = new Hybrid("pinapple1")
var hybrid2 = new Hybrid("pinapple2")

hybrid1.getname() //bigsecret-->pinapple1-->pinapple2-----pinapple1
hybrid2.getname() //bigsecret-->pinapple1-->pinapple2-----pinapple2
console.log(hybrid1.deepsecret()) //secret that no one should know---pinapple1
console.log(hybrid2.deepsecret()) //secret that no one should know---pinapple2

基本上,该函数为其内部Tree的构造函数提供了一个闭包Treprivatename您可以使用在匿名函数之外Tre但在匿名函数内部的那个,而不是使用最深的Tree

于 2018-03-04T14:01:55.820 回答