【问题标题】:prototype behavior in javascriptjavascript中的原型行为
【发布时间】:2013-06-18 21:49:24
【问题描述】:

我对 javascript 中的以下原型行为感到困惑。

function A(){
};

A.prototype.toString = function(){
            console.log('first');
               }

var a = new A(), b;

A.prototype = {
    toString:function(){
        console.log('second');
    }
}

b = new A();

a.toString();
//outputs :  first

b.toString();
//outputs :  second

与打印“second”的 b.toString 相比,为什么 a.toString 仍然打印“frist”。 谁能解释一下我在这里缺少什么。

【问题讨论】:

  • 为什么是var a = new A(), b
  • @basilikum:哦,我误解了,他只是将b 声明为 var。一切都很好。

标签: javascript prototype-programming function-prototypes prototype-oriented


【解决方案1】:

原型链接与构造的构造函数无关 对象,它存储在对象本身上。

当您致电new A() 时,会发生这种情况:

var a = {};
a.__proto__ = A.prototype;
A.call(a);

请注意,以上不是标准语法,但在 chrome 和 firefox 中确实有效。

因此,当您覆盖 A.prototype 时,a.__proto__ 仍然链接到旧的 A.prototype,正如您所期望的类似 代码:

var A = 10, a, b;

a = A;
A = 7; //a is still 10
b = A; 

我不建议重新分配原型,因为那样你需要重新建立构造函数属性并且它需要额外的缩进级别。

如果你想输入更少,只需存储对原型的引用:

function A() {

}
var fn = A.prototype;

fn.toString = function() {

};

fn.valueOf = function() {

};

fn.toJSON = function() {

};

【讨论】:

  • 我不会说“什么都没有”,而是对象的 [[Prototype]] 设置为构造函数的原型在构造对象时
  • @RobG 这基本上是在说同样的话:P。我只是想消除构造函数在外面监视所有创建的实例或其他东西的信念。
  • 是的,相同但不同。 :-)
【解决方案2】:

函数 A(){ };

A.prototype.toString = function(){
            console.log('first');
               }     // here A prints 'first'

var a = new A(), b;  

A.prototype = {    
    toString:function(){
        console.log('second');
    }
}                    // here A prints 'second'

b = new A();

a.toString();
//outputs :  first

b.toString();
//outputs :  second

【讨论】:

    【解决方案3】:

    一个对象的内部[[Prototype]](它继承自的那个)被设置为其构造函数的原型在它被构造的时候。将新对象分配给构造函数的原型不会改变已创建实例的[[Prototype]]

    事实上,一旦创建了一个对象,除了非标准的__proto__ property 之外,您不能分配不同的[[Prototype]]

    编辑

    只是为了说清楚:

    // A simple constructor
    function Person(name) {
      this.name = name;
    }
    
    // Assign a method to its default prototype
    Person.prototype.showName = function() {
      return this.name;
    }
    
    // This instance will be assigned the above as its [[Prototype]]
    // with its showName method
    var fred = new Person('Fred');
    
    // Assign a new object to Person.prototype 
    Person.prototype = {};
    
    // Assign a new showName method
    Person.prototype.showName = function() {
      return 'My name is ' + this.name;
    }
    
    // This instance has the new object as its [[Prototype]]
    var sue = new Person('Sue');
    
    console.log(
        fred.showName() + '\n'  // Fred 
      + sue.showName()          // My name is Sue
    );
    

    可以看出,fred仍然继承自原原型对象,sue继承自新对象,因为它是在更改后创建(实例化)的。 p>

    【讨论】:

    • 这是怎么回事obj = {foo:{a:1}, b:1}; function Class(){}; Class.prototype = obj; y = new Class(); y.foo.a = 2; // prints 2 x = new Class(); x.foo.a // prints 2
    • 因为当 xy 具有相同的对象( obj) 作为其原型,因此 xy 具有相同的[[Prototype]](即 obj)。如果您在创建 x 之前更改Class.prototype,它将继承自新对象,并且将具有与 y 不同的[[Prototype]]
    猜你喜欢
    • 2015-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 2016-04-10
    • 1970-01-01
    相关资源
    最近更新 更多