【问题标题】:difference between using this and prototype to define methods of a class in JavaScript? [duplicate]在 JavaScript 中使用 this 和原型定义类的方法有什么区别? [复制]
【发布时间】:2012-08-01 22:13:18
【问题描述】:

可能重复:
Javascript - this Vs. prototype
Advantages of using prototype, vs defining methods straight in the constructor?
Prototype or inline, what is the difference?

在 JavaScript 中创建类时,使用 this 在对象内部声明方法与通过访问 prototype 声明方法有何不同?在我看来,这也是为了同样的目的。

window.onload = function() { 
    tc = new TestClass();
    tc.init(); //logs initting
    tc.reset(); //logs resetting
    tc.doSomething(); //logs doing something
};


var TestClass = function(){

    this.init = function(){
        console.log("initting");
    }

    this.reset = function(){
        console.log("resetting");
    }

    this.destroy = function(){
        console.log("destroying");
    }

}

TestClass.prototype.doSomething = function(){

    console.log("doing something");
}

【问题讨论】:

    标签: javascript oop prototypejs prototype-programming


    【解决方案1】:

    在您阅读之前:英语不是我的母语;)

    在实践中thisprototype几乎相同,但thisprototype在javascript。

    1) Javascript 基于原型继承。这意味着一个对象可以从另一个对象继承原型模型。使用原型,您可以模拟 javacript 上的继承(有限制),例如:

    // create a 'class' Vehicle
    var Vehicle = function() {};
    Vehicle.prototype.wheels = 0;
    Vehicle.prototype.maxSpeed = 0;
    Vehicle.prototype.displayInfo = function() { 
         alert("hello, I have " + this.wheels + " wheels and max speed of " + this.maxSpeed);
    };
    
    var vehicleInstance = new Vehicle();
    vehicleInstance.displayInfo(); // displays: Hello, I have 0 wheels and max speed of 0
    
    // create a 'class' Car using the prototype from Vehicle 
    // and change some properties.
    var Car = function(maxSpeed) { 
        if(maxSpeed)
          this.maxSpeed = maxSpeed;
    };
    // inherit the prototype from vehicle
    Car.prototype = new Vehicle();  
    // change some properties
    Car.prototype.maxSpeed = 200;
    Car.prototype.wheels = 4;
    
    var car = new Car();
    car.displayInfo(); // displays: Hello, I have 4 wheels and max speed of 200
    

    2) this 中的属性优先于 prototype 中的属性,例如:

    var car = new Car(); // car prototype: maxSpeed = 200;
    car.displayInfo() // displays: Hello, I have 4 wheels and max speed of 200
    
    //set maxSpeed to 300 on 'this'
    var car = new Car(300); // see Car definition above
    
    // call displayInfo() in car instance. The Car 'class' doesn't have displayInfo()
    // itself, but its prototype has. The javascript VM will look
    // for displayInfo() in the car instance, if it not found in the
    // instance it will look in car.prototype and on car.prototype.prototype etc.
    // until it founds a property called displayInfo() 
    // or reaches the end of the chain (Object.prototype).
    car.displayInfo() // displays: Hello, I have 4 wheels and max speed of 300
    

    这也适用于原型的原型,例如。

    var Class1 = function() { };
    Class1.prototype.someValue = 1;
    
    var Class2 = function() { };
    Class2.prototype = new Class1();
    Class2.prototype.someValue = 2; // this overrides the Class1.prototype.someValue prototype
    
    var class2 = new Class2();
    class2.someValue = 3; // this overrides the Class2.prototype.someValue;
    

    3) 在原型上定义的属性不会为同一对象的每个新实例实例化,例如:

    // create a new class and inherit the prototype model from Vehicle.
    var Motorcycle = function() { };
    Motorcycle.prototype = new Vehicle();
    // motorcycles has 2 wheels
    Motorcycle.prototype.wheels = 2;
    
    var motorcycle = new Motorcycle();
    motorcycle.dysplayInfo(); // displays: Hello, I have 2 wheels and max speed of 200
    
    //now, if I change the method dysplayInfo from Vehicle, it will change for every
    //object that inherits Vehicle prototype:
    Vehicle.prototype.displayInfo = function() { 
        Alert("Wheels: " + this.wheels + ", Max speed: " + this.maxSpeed);
    }
    
    //observe that I didn't create another Motorcycle instance ,
    //I'm using the same instance that I've created before change
    //the Vehicle.dysplayInfo() method
    motorcycle.displayInfo() // displays: Wheels: 2, Max speed: 200
    

    如您所见,任何继承其原型的对象都使用在 Vehicle 中使用的相同方法。这使您的代码更加高效,因为您对多个对象使用相同的函数。您可以从胖原型继承数千个对象,但内存占用仍然很低。

    简而言之: 通过使用原型,您可以创建强大的“类类”对象,具有定义明确的继承树(我们说原型链),它将更有效地运行并使用更少的内存。

    我在这里所说的并没有穷尽原型继承/链的主题。以下是您可以阅读的其他资源。我推荐,因为理解 javascript 中的原型对于编写良好且可维护的代码至关重要。

    我在这里所说的并没有穷尽原型的主题: https://developer.mozilla.org/en-US/docs/JavaScript/Introduction_to_Object-Oriented_JavaScript?redirectlocale=en-US&redirectslug=Introduction_to_Object-Oriented_JavaScript

    http://javascript.crockford.com/prototypal.html

    http://javascriptweblog.wordpress.com/2010/06/07/understanding-javascript-prototypes/

    【讨论】:

      【解决方案2】:

      在这种特殊情况下,它们具有相同的效果,但它们却大不相同。一个(?)主要区别是使用 this 附加的方法是对象本身的属性,而不是其原型的属性,因此像这样迭代对象:

      for(var x in tc) {
          if(tc.hasOwnProperty(x)) {
              console.log('Has property ' + x);
          }
      }
      

      将省略使用prototype 添加的方法。另一个区别是引用。将方法分配给this 每次都会创建新的函数对象,但使用原型,它们都是相同的函数。 (这可能是也可能不是您想要的,在将额外属性附加到方法时最重要。)

      【讨论】:

      • 请问还有哪些不同之处?
      • @nuway: 其他的差异几乎是它的扩展。
      【解决方案3】:

      在大多数情况下,您将获得相同的功能结果。但在内部,它完全不同,当您将函数附加到this 时,该类型的每个实例都会获得它自己的函数副本。通过将函数附加到prototype,所有实例共享相同的函数实例。使用原型可以减少内存使用。

      【讨论】:

      • @nuway:尽量不要用经典的术语去想太多;当幻觉破灭时,它会让你发疯。 JS 没有类,因此没有static。在 JS 中,您有原型(只是常规对象),其他对象直接继承自原型而不是其类。也就是说,原型是一个实例。原型上的东西被从原型继承的所有东西继承......但它不是“静态的”,因为原型中的任何功能仍然可以在this上工作并做正确的事情。
      • 更重要的是,“静态”的东西可以随意覆盖而不会破坏兄弟对象。如果你的原型上有一个x,值为'1',你说this.x = 0;,你会得到你自己的x——这看起来就像原型的版本(当然除了不同的值,和you.hasOwnProperty('x')true) 返回到任何与您混淆的函数,甚至是原型中的函数。
      猜你喜欢
      • 2013-05-26
      • 1970-01-01
      • 1970-01-01
      • 2013-08-09
      • 1970-01-01
      • 1970-01-01
      • 2011-03-21
      • 1970-01-01
      • 2016-01-02
      相关资源
      最近更新 更多