深入浅出剖析__proto__和prototype之间的关系,揭开JavaScript运行机制
2023-10-03 07:22:19
在JavaScript的世界中,prototype
和 __proto__
是两个经常被提及的概念。它们密切相关,同时也是JavaScript运行机制的重要组成部分。为了更好地理解它们,我们需要从对象的创建和继承说起。
JavaScript中的对象创建和继承
JavaScript中的对象可以通过两种方式创建:通过对象字面量或通过构造函数。
- 对象字面量 :使用花括号(
{}
)创建的对象。例如:
const person = {
name: "John Doe",
age: 30,
};
- 构造函数 :使用
new
调用函数创建的对象。例如:
function Person(name, age) {
this.name = name;
this.age = age;
}
const person = new Person("John Doe", 30);
当通过构造函数创建对象时,JavaScript会自动在对象中创建一个名为 __proto__
的属性,指向该对象的构造函数的 prototype
属性。因此,对于上例中的 person
对象,person.__proto__
将指向 Person.prototype
。
prototype和__proto__之间的关系
prototype
和 __proto__
之间的联系十分紧密,我们可以通过一个简单的示例来说明。
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};
const person = new Person("John Doe", 30);
person.sayHello(); // Hello, my name is John Doe and I am 30 years old.
在这个示例中,我们首先定义了一个 Person
构造函数,并在其 prototype
属性上添加了一个 sayHello
方法。然后,我们使用 new
关键字创建了一个 person
对象。当我们调用 person.sayHello()
时,JavaScript 会在 person
对象中查找 sayHello
方法。由于 person
对象中没有 sayHello
方法,JavaScript 会沿 person
对象的原型链向上查找,直到找到 Person.prototype
。在 Person.prototype
中找到了 sayHello
方法,JavaScript 就会调用该方法。
如何利用prototype和__proto__实现对象继承
JavaScript 中的对象继承是通过 prototype
和 __proto__
实现的。当我们通过构造函数创建对象时,JavaScript 会自动在对象中创建一个 __proto__
属性,指向该对象的构造函数的 prototype
属性。因此,子对象的 __proto__
属性指向父对象的 prototype
属性,从而实现了对象继承。
例如,如果我们想要创建一个 Student
类,并让 Student
类继承 Person
类,我们可以这样做:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};
function Student(name, age, major) {
Person.call(this, name, age);
this.major = major;
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
const student = new Student("John Doe", 30, "Computer Science");
student.sayHello(); // Hello, my name is John Doe and I am 30 years old.
在这个示例中,我们首先定义了一个 Person
类,并在其 prototype
属性上添加了一个 sayHello
方法。然后,我们定义了一个 Student
类,并在其构造函数中调用 Person.call(this, name, age);
来继承 Person
类的属性和方法。接下来,我们使用 Object.create(Person.prototype)
来创建 Student.prototype
,并将其赋值给 Student.prototype
。最后,我们使用 Student.prototype.constructor = Student;
来修复 Student
类的 constructor
属性,使其指向 Student
函数。
现在,当我们创建一个 student
对象时,JavaScript 会自动在 student
对象中创建一个 __proto__
属性,指向 Student.prototype
。由于 Student.prototype
继承了 Person.prototype
,因此 student
对象也继承了 Person
类的属性和方法。