在 JavaScript 的世界中,原型和原型链是理解这门语言面向对象编程(OOP)机制的核心。不同于传统的基于类的语言如 Java,JavaScript 采用了一种独特的原型继承机制。本文将深入探讨 __proto__
和 prototype
的由来、关系以及它们在 JavaScript 中的作用。
传统的面向对象编程语言(如 Java)具有类、继承、封装和多态等特性。JavaScript 虽然也支持 OOP,但其实现方式却大不相同。
在 ES6 之前,JavaScript 并没有 class
关键字。为了实现类似类的功能,开发者通常使用构造函数和原型来模拟类的行为。例如:
// Java 中的类定义
public class Puppy {
int puppyAge;
public Puppy(int age) {
puppyAge = age;
}
public void say() {
System.out.println("汪汪汪");
}
}
而在 JavaScript 中,我们通过函数来模拟类:
// JavaScript 中的构造函数模拟类
function Person(name, age) {
this.name = name;
this.age = age;
}
虽然可以通过对象字面量创建对象,但当需要创建多个相似对象时,这种方式显得非常繁琐:
var Person = {
name: '吉他胡',
hobbies: ['弹吉他', '弹钢琴'],
}
var pll = {
name: '皮乐乐',
hobbies: ['弹吉他', '弹钢琴'],
}
为了解决这个问题,JavaScript 引入了构造函数和原型的概念。
构造函数是 JavaScript 中模拟类的关键。通过约定俗成,构造函数的名称首字母大写:
function Person(name, age) {
this.name = name;
this.age = age;
}
prototype
属性每个函数都有一个 prototype
属性,它是一个对象,用于存储共享的属性和方法。通过将方法定义在 prototype
上,可以避免每次实例化对象时重复创建方法:
Person.prototype.sayHello = function() {
console.log(`hello, my name is ${this.name}`);
}
__proto__
属性每个对象都有一个私有属性 __proto__
,它指向构造函数的 prototype
对象。例如:
let hu = new Person('吉他胡', 18);
console.log(hu.__proto__ === Person.prototype); // true
__proto__
是对象与构造函数之间的桥梁,也是原型链实现的基础。
JavaScript 中的继承是通过原型链实现的。当访问一个对象的属性或方法时,如果对象本身没有该属性,JavaScript 会沿着 __proto__
向上查找,直到找到该属性或到达原型链的顶端(Object.prototype
),最终指向 null
。
console.log(hu.toString()); // 调用的是 Object.prototype.toString
__proto__
可以动态修改,从而改变对象的原型链:
var a = {
name: '孔子',
country: '中国',
};
hu.__proto__ = a;
console.log(hu.country); // 输出:中国
原型链的顶端是 Object.prototype
,其 __proto__
指向 null
:
console.log(Object.prototype.__proto__); // null
new
的过程当我们使用 new
关键字创建对象时,JavaScript 会执行以下步骤:
{}
。this
指向这个空对象。__proto__
指向构造函数的 prototype
。let hu = new Person('吉他胡', 18);
prototype
与 __proto__
的关系prototype
:是函数特有的属性,指向构造函数的原型对象。__proto__
:是对象特有的属性,指向构造函数的 prototype
对象。它们的关系可以用以下代码验证:
console.log(Person.prototype.constructor === Person); // true
console.log(hu.__proto__ === Person.prototype); // true
prototype
是函数特有的属性,用于定义共享的属性和方法。__proto__
是对象特有的属性,用于构建原型链。__proto__
向上查找属性和方法。new
关键字 通过构造函数创建对象,并建立原型链关系。理解原型和原型链是掌握 JavaScript 面向对象编程的关键。虽然 ES6 引入了 class
语法,但其底层仍然是基于原型的实现。希望本文能帮助你更好地理解 JavaScript 的原型机制!