3

我正在学习 JS Prototype。

如果我从其他构造函数(B)的实例设置构造函数(A)的原型,那么(B)实例是否会在 A 中引入共享属性?

示例 1

function A(){ 
    var private = '';

    this.getPrivate = function(){ 
        return private
    }; 

    this.setPrivate = function(_private){ 
        private = _private; 
    }; 
}

function B(){};

B.prototype = new A();

b1 = new B();
b2 = new B();

b1.setPrivate(new Date());
b2.getPrivate(); // Here `private` is behaving as singleton property. Why?

示例 2

function A(){ 
    var private = '';
}

A.prototype.getPrivate = function(){ 
    return this.private
}; 

A.prototype.setPrivate = function(_private){ 
    this.private = _private; 
}; 

function B(){};

B.prototype = new A();

b1 = new B();
b2 = new B();

b1.setPrivate(new Date());
b2.getPrivate(); // This time private is not singleton property.

我在玩它时发现了原型的这个新方面。

  • 在示例 1 中,为什么private在 的不同实例之间共享属性B
  • 在示例 2 中,为什么private财产在两种情况下都具有独立存在?但是原始属性没有改变,但是 getter/setter 是通过原型定义的。
  • 可以将示例 1 视为单例属性的实现吗?
  • 通过实例进行原型设计和通过原型进行原型设计,有什么区别?例如
    B.prototype = new A();
    B.prototype = (new A()).constructor.prototype
  • 原型设计的全部秘密是什么?
4

4 回答 4

1

原型设计的秘密(解释了这一切)是每个实例B共享相同的原型,即原型不会复制到B. 当您触发 的任何实例的原型函数时B,您实际上一直在运行相同的函数。这就是复制“私有”变量的原因(实际上它没有被复制,您只是一直在引用同一个变量)。“非私有”变量的行为相同,不同之处在于关键字this指的是函数的当前“持有者”。这就是为什么在原型中调用this给我们一种原型方法实际上是对象的方法的错觉。它不是。

通过实例进行原型设计被认为是不好的做法,因为实例可能具有或多或少的属性,具体取决于它们何时被调用以及何时进行原型设计。原型主要通过字面量对象创建扩展其他对象的原型来定义。

最后:在某种意义上,原型设计可能被解释为单例。

于 2012-06-26T19:29:06.907 回答
1
  1. 因为您正在继承锁定到特定闭包的特定实例。数据属于闭包而不是对象。对象的变量和属性之间存在巨大差异。

  2. 这里var private根本不使用。当您setPrivate()在该点创建属性时。

  3. 不,这只是由于闭包和对象模型之间的误解而造成的。你可以用一种更深思熟虑、更清晰的方式来做同样的事情:使用简单的对象字面量。

  4. 不同之处在于,在第一个中你得到一个新对象,而在第二个中你有一个A.prototype === B.prototype所以修改一个会修改另一个,因为它们引用了同一个对象。

  5. 对象继承自其他对象

这是一个很好的资源https://developer.mozilla.org/en/JavaScript/Guide/Details_of_the_Object_Model

于 2012-06-26T19:32:29.320 回答
1

在示例 1 中,为什么私有财产在 B 的不同实例之间共享?

是的,他们有

在示例 2 中,为什么私有财产在两种情况下都有独立存在?但是原始属性没有改变,但是 getter/setter 是通过原型定义的。

因为每个实例都独立于其他实例。如果这不是您想要的,请使用对象文字表示法来创建您的类。

可以将示例 1 视为单例属性的实现吗?

不,因为单例总是返回相同的对象实例。这与您的第二个问题有关,每个实例都是独立的。可以从您的第一个示例中创建该类的许多实例。要创建单例,存在单例或模块模式,它使用带有分组运算符的自调用函数,例如.()

通过实例进行原型设计和通过原型进行原型设计,有什么区别?例如

使用constructor,您可以确保子类构造函数和父类之间没有混淆。扩展父类时也是同样的概念,在子类中你在子类的构造函数中构造父类。

原型设计的全部秘密是什么?

浏览各种 JS Ninja 博客上的好文章。我爱:

这是一篇好文章:

于 2012-06-26T19:38:01.397 回答
1

在示例 1 中,您使用闭包范围来引用私有。由于 A 仅实例化一次,因此定义了它的一个实例。

在示例 2 中,this.private 没有引用函数 A 中的 private 实例。事实上,由于您使用“this”这个词,它指的是对象的“this”。因此, this.private 要么意味着 b1.private 要么 b2.private 取决于功能。在示例 2 中,函数 A 中定义的私有在闭包范围内丢失,就好像它从未定义过一样。

于 2012-06-26T19:52:56.940 回答