原型与原型链探秘

684 阅读3分钟

在JavaScript的世界里,"原型"(Prototype)是一个核心而又微妙的概念,它支撑着语言中面向对象编程的基础。理解原型可以帮助我们更深入地掌握JavaScript的机制,特别是对象的继承和属性查找过程。本文将围绕原型、原型链以及隐式原型这三个概念展开,揭示它们如何共同作用,构建起JavaScript动态而灵活的对象体系。

原型(Prototype)

每个JavaScript函数都有一个特殊的属性——prototype。这个属性指向一个对象,即所谓的“原型对象”。当我们使用某个构造函数(如function Person() {})通过new关键字创建新对象时,这个新对象会自动链接到构造函数的prototype对象上。这意味着,构造函数prototype上定义的所有属性和方法都会被新创建的实例所共享。因此,原型提供了一种实现对象间属性和方法继承的机制。打个比方:你父母把你new(生下来)之后,你就拥有了父母财产的继承权

function Person(name) {
    this.name = name;
}

Person.prototype.sayHello = function() {
    console.log("Hello, my name is " + this.name);
};

var person1 = new Person("Alice");
person1.sayHello(); // 输出 "Hello, my name is Alice"

在这个例子中,所有通过Person构造函数创建的对象都能访问到sayHello方法,因为这个方法定义在Person.prototype上。

原型链(Prototype Chain)

当访问一个对象的属性或方法时,如果该对象本身没有定义该属性或方法,JavaScript引擎并不会立即报错,而是会继续在其__proto__属性(即隐式原型)所指向的对象中寻找。这个过程会一直向上追溯,直到找到该属性或方法,或者遇到null(表示到达原型链的末端)。这一系列的查找路径就构成了“原型链”。再打个比方:这里的对象就是你,原型链就相当于你的族谱,当没在你这找到,就顺着你的族谱找,找到你的父亲、爷爷......一级一级往上找,直到找到或者族谱翻完为止

Object.prototype.isPrototypeOf(person1); // true,说明person1的原型链上包含Object.prototype

通过原型链,对象可以继承其构造函数原型以及整个原型链上定义的所有属性和方法,实现了基于原型的继承机制。

隐式原型(proto

每个JavaScript对象(除null外)都有一个内部属性__proto__,它指向该对象的原型。简而言之,obj.__proto__就是构造函数的prototype属性。尽管__proto__在一些环境下可直接访问,但它并不是标准的一部分,更推荐使用Object.getPrototypeOf(obj)来获取一个对象的原型。

console.log(person1.__proto__ === Person.prototype); // true

所有对象都有原型吗?

并非如此。通过Object.create(null)创建的对象是一个特例,它没有原型。这意味着该对象的__proto__null,不继承任何属性或方法。

var objWithoutProto = Object.create(null);
console.log(objWithoutProto.__proto__); // null

测验

你能看懂下面这个图吗?

1632878-20190507094639999-1584111224.png

总结

总结来说,原型机制是JavaScript中实现继承和对象属性查找的核心。通过理解原型、原型链以及隐式原型,我们可以更深刻地认识到JavaScript对象之间的关系与互动方式,进而编写出更加高效、灵活的代码。而Object.create(null)的特例,则提醒我们在设计对象结构时拥有更多的灵活性和选择性。

好的,这次的内容就分享到这了,如果小友觉得整的还不错的,可以留下一个小小的赞帮助俺找回自己的脑子,谢谢啦!!!