【问题标题】:Understanding javascript prototype了解 javascript 原型
【发布时间】:2012-06-26 19:23:55
【问题描述】:

我正在学习 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
  • 原型设计的全部秘密是什么?

【问题讨论】:

    标签: javascript prototype-programming


    【解决方案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

    【讨论】:

    • 是的,一个简单的对象字面量可以是单例对象的慎重选择。但是可以通过这种方式实现部分单例属性。我有一个场景,不同的 fx 对象拥有独立的配置,但共享它们操作的 dom 元素的引用。
    • @ShuaibNawaz 我不熟悉partial单例的概念:P
    • 我不会创造一个新术语。 :D 我的意思是在实例之间定义一些共享属性,它适用于我的场景,我不清楚它的概念。无论如何谢谢你。
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

      是的

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

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

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

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

      通过实例进行原型设计和通过原型进行原型设计,分别是什么 不同之处?例如

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

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

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

      这是一篇好文章:

      【讨论】:

        【解决方案4】:

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2010-10-27
          • 2014-08-20
          • 1970-01-01
          • 2016-10-31
          • 1970-01-01
          • 1970-01-01
          • 2014-04-01
          • 2018-11-01
          相关资源
          最近更新 更多