JavaScript中的原型与原型链
原创什么是原型
在JavaScript中,每个对象都有一个特殊的隐藏属性[[Prototype]](可以通过__proto__访问),该属性要么为null,要么是对另一个对象的引用。这个被引用的对象称为"原型"。
当我们试图读取一个对象的属性或方法时,如果对象本身没有这个属性,JavaScript会自动从它的原型中寻找,然后在原型的原型上寻找,以此类推,直到找到该属性或者到达原型链的末端(null)。
let animal = { eats: true};let rabbit = { jumps: true};rabbit.__proto__ = animal; // 设置rabbit的原型为animalconsole.log(rabbit.jumps); // true (来自rabbit自身)console.log(rabbit.eats); // true (来自原型animal)原型链
原型链是由一系列对象通过[[Prototype]]链接形成的链条。当访问一个对象的属性时:
JavaScript首先检查对象自身是否有该属性如果没有,则检查对象的原型(__proto__)继续向上检查原型的原型,直到找到属性或到达null
let animal = { eats: true, walk() { console.log("Animal walk"); }};let rabbit = { jumps: true, __proto__: animal};let longEar = { earLength: 10, __proto__: rabbit};// walk是原型链上找到的longEar.walk(); // Animal walkconsole.log(longEar.jumps); // true (来自rabbit)函数的prototype属性
在JavaScript中,函数也是一个对象,每个函数都有一个prototype属性。这个属性只有在函数作为构造函数使用时才有意义。
当我们使用new操作符调用函数时,新创建对象的[[Prototype]]会被设置为该函数的prototype属性。
function Animal(name) { this.name = name;}Animal.prototype.sayName = function() { console.log("My name is " + this.name);};let cat = new Animal("Mimi");cat.sayName(); // My name is Mimi现代获取和设置原型的方法
虽然__proto__被广泛支持,但现代JavaScript提供了更推荐的方法:
Object.getPrototypeOf(obj) - 返回对象obj的[[Prototype]]Object.setPrototypeOf(obj, proto) - 将对象obj的[[Prototype]]设置为proto
let animal = { eats: true};let rabbit = Object.create(animal); // 创建一个新对象,以animal为原型console.log(rabbit.eats); // trueconsole.log(Object.getPrototypeOf(rabbit) === animal); // trueObject.setPrototypeOf(rabbit, {}); // 将rabbit的原型更改为{}console.log(rabbit.eats); // undefined原型在实际中的应用
理解原型有助于我们编写更高效的代码:
// 通过原型共享方法,节省内存function Person(name) { this.name = name;}Person.prototype.greet = function() { console.log(`Hello, my name is ${this.name}`);};let john = new Person("John");let jane = new Person("Jane");john.greet(); // Hello, my name is Johnjane.greet(); // Hello, my name is Jane// 两个对象共享同一个greet方法console.log(john.greet === jane.greet); // true原型是JavaScript实现继承的基础,也是理解这门语言核心特性的关键概念之一。
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权本站发表,未经许可,不得转载。
开发学习网




