JavaScript原型与原型链深入探究使用方法
原型
JavaScript中每个函数都有一个prototype
属性,它指向一个对象。这个对象就是所谓的“原型对象”或“原型”。我们可以在原型对象上添加方法和属性,这些方法和属性可以被构造函数创建的实例所共享。在原型对象上定义的方法和属性,可以被该构造函数所创建的所有实例共享使用。这样,我们就可以省略实例中相同的方法和属性了。
我们可以使用Object.getPrototypeOf()
方法获取指定对象的原型对象,或者使用对象的__proto__
属性获取其原型对象。
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function() {
console.log("Hello, I'm " + this.name + " and I'm " + this.age + " years old.");
};
var p1 = new Person("Alice", 23);
var p2 = new Person("Bob", 24);
p1.sayHello(); // Hello, I'm Alice and I'm 23 years old.
p2.sayHello(); // Hello, I'm Bob and I'm 24 years old.
console.log(Object.getPrototypeOf(p1) === Person.prototype); // true
console.log(p1.__proto__ === Person.prototype); // true
原型链
JavaScript中除了Object
对象没有原型,其他所有对象都有原型。当我们访问对象的一个属性时,JavaScript引擎会首先在该对象本身查找该属性,如果找到则直接返回该属性的值;如果没有找到,则继续在该对象的原型对象上查找该属性。如果仍然没有找到,则继续在原型对象的原型对象上查找,直到找到该属性或到达Object为止。
这种由多个对象构成的链式结构就是原型链。我们可以使用Object.create()
方法来创建一个指定对象的新对象,并把新对象的原型对象指定为该指定对象,从而形成一个原型链。
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function() {
console.log("Hello, I'm " + this.name + " and I'm " + this.age + " years old.");
};
function Student(name, age, grade) {
Person.call(this, name, age);
this.grade = grade;
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
Student.prototype.sayGrade = function() {
console.log(this.name + "'s grade is " + this.grade + ".");
};
var s1 = new Student("Alice", 23, "A");
var s2 = new Student("Bob", 24, "B");
s1.sayHello(); // Hello, I'm Alice and I'm 23 years old.
s1.sayGrade(); // Alice's grade is A.
s2.sayHello(); // Hello, I'm Bob and I'm 24 years old.
s2.sayGrade(); // Bob's grade is B.
console.log(Object.getPrototypeOf(s1) === Student.prototype); // true
console.log(Object.getPrototypeOf(Student.prototype) === Person.prototype); // true
console.log(Object.getPrototypeOf(Person.prototype) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype) === null); // true
在上面的示例中,使用Object.create()
方法创建了一个新对象,并把原型对象指定为Person.prototype
,从而形成了一个原型链。由于我们重写了Student.prototype
对象,导致其原型对象不再指向Object.prototype
,所以要手动给Student.prototype
重新设置constructor
属性。在该原型链中,Student
的实例Student.prototype
的原型对象是Person.prototype
,Person
的实例的原型对象是Object.prototype
,最高层原型对象是null
。为了提高代码的可读性,我们可以使用ES5中新增的Object.setPrototypeOf()
方法来设置对象的原型对象。
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function() {
console.log("Hello, I'm " + this.name + " and I'm " + this.age + " years old.");
};
function Student(name, age, grade) {
Person.call(this, name, age);
this.grade = grade;
}
Object.setPrototypeOf(Student.prototype, Person.prototype);
Student.prototype.sayGrade = function() {
console.log(this.name + "'s grade is " + this.grade + ".");
};
var s1 = new Student("Alice", 23, "A");
var s2 = new Student("Bob", 24, "B");
s1.sayHello(); // Hello, I'm Alice and I'm 23 years old.
s1.sayGrade(); // Alice's grade is A.
s2.sayHello(); // Hello, I'm Bob and I'm 24 years old.
s2.sayGrade(); // Bob's grade is B.
console.log(Object.getPrototypeOf(s1) === Student.prototype); // true
console.log(Object.getPrototypeOf(Student.prototype) === Person.prototype); // true
console.log(Object.getPrototypeOf(Person.prototype) === Object.prototype); // true
console.log(Object.getPrototypeOf(Object.prototype) === null); // true
示例说明
示例一
在以下示例中,我们定义了一个Animal
的构造函数,该构造函数拥有一个eat
方法的原型。我们接着从Animal
继承一个Dog
构造函数,并通过原型链给Dog
添加一个bark
方法。最后,使用Dog
构造函数创建了一个d
对象。我们可以发现,d
可以调用eat
和bark
两个方法。
function Animal(name) {
this.name = name;
}
Animal.prototype.eat = function() {
console.log(this.name + " is eating.");
};
function Dog(name) {
this.name = name;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.bark = function() {
console.log(this.name + " is barking.");
};
var d = new Dog("Gunner");
d.eat();
d.bark();
示例二
在以下示例中,我们定义了一个Shape
的构造函数,该构造函数拥有一个getType
方法的原型。我们接着从Shape
继承一个Rectangle
构造函数,并重写了该构造函数的getType
方法来返回特定的type
属性。最后,使用Rectangle
构造函数创建了一个r
对象。我们可以发现,r
的getType
方法返回了rectangle
。
function Shape() { }
Shape.prototype.getType = function() {
return "shape";
}
function Rectangle() { }
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
Rectangle.prototype.getType = function() {
return "rectangle";
}
var r = new Rectangle();
console.log(r.getType());
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JavaScript原型与原型链深入探究使用方法 - Python技术站