使用这个和原型在JavaScript中定义类的方法之间的区别?

时间:2012-08-03 20:34:13

标签: javascript oop prototypejs prototype-programming

  

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

在JavaScript中创建类时,如何使用 this 声明对象内的方法,然后通过访问原型来声明它?在我看来,服务于同样的目的。

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");
}

3 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:2)

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

在实践中,原型几乎相同,但原型具有不同的含义的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)中的属性优先于原型中的属性,例如:

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 :(得分:1)

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

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

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

相关问题