在JavaScript中使用这个和原型来定义类的方法有什么区别?
可能重复:在JavaScript中使用这个和原型来定义类的方法有什么区别?,javascript,oop,prototypejs,prototype-programming,Javascript,Oop,Prototypejs,Prototype Programming,可能重复: 在JavaScript中创建类时,使用this在对象内部声明方法与通过访问原型来声明方法有何不同?在我看来,这也有同样的目的 window.onload = function() { tc = new TestClass(); tc.init(); //logs initting tc.reset(); //logs resetting tc.doSomething(); //logs doing something }; var Test
在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");
}
在大多数情况下,您将获得相同的功能结果。但在内部,它是完全不同的,当您将函数附加到
this
时,该类型的每个实例都会获得它自己的函数副本。通过将函数附加到原型
,所有实例共享相同的函数实例。使用prototype可以减少内存使用。在特定情况下,它们具有相同的效果,但它们非常不同。一个主要区别是使用this
附加的方法是对象本身的属性,而不是其原型的属性,因此像这样迭代对象:
for(var x in tc) {
if(tc.hasOwnProperty(x)) {
console.log('Has property ' + x);
}
}
将省略使用
prototype
添加的方法。另一个区别是参考文献;将方法分配给此
每次都将创建新的函数对象,但使用原型,它们都是相同的函数。(这可能是您想要的,也可能不是您想要的,并且在为方法附加额外属性时最为重要。)在阅读之前:英语不是我的母语;)
实际上,这个和原型几乎是一样的,但是这个和原型在javascript中有不同的含义
1) Javascript基于原型继承。这意味着一个对象可以从另一个对象继承原型模型。使用prototype,您可以在JavaScript上模拟继承(有限制),例如:
// 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
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
// 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
2) 中的属性此优先于原型中的属性,例如:
// 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
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
// 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
例如,这也适用于原型的原型
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 '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
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
// 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
正如您所看到的,车辆中使用的相同方法用于继承其原型的任何对象。这将使您的代码更加高效,因为您对多个对象使用相同的函数。您可以从fat原型继承数千个对象,但仍然会占用较低的内存
简言之:
通过使用prototype,您可以创建功能强大的“类”对象,并具有定义良好的继承树(我们称之为prototype链),该继承树运行效率更高,占用内存更少
我在这里所说的并没有穷尽原型继承/链的主题。以下是您可以阅读的其他资源。我推荐您,因为了解javascript中的原型对于编写良好且可维护的代码至关重要
我在这里所说的并没有穷尽原型的主题:
请问还有什么不同之处?@nuway:其他不同之处几乎就是它的延伸。@nuway:尽量不要用经典的术语去想太多;当幻想破灭时,你会发疯的。JS没有类,因此没有静态的
。在JS中,您有原型(只是常规对象),其他对象直接从原型继承,而不是从其类继承。也就是说,原型是一个实例。原型上的内容由从原型继承的所有内容继承……但它不是“静态的”,因为原型中的任何函数仍然可以处理这个,并做正确的事情。此外,“静态”内容可以随意重写,而不会破坏兄弟对象。如果原型上有一个值为“1”的x
,你说this.x=0
,您可以获得自己的x
——这看起来就像原型的版本(当然,除了不同的值,以及you.hasOwnProperty('x')
返回true
)到任何与您有冲突的函数,甚至原型中的函数。