JS原型和原型链:一文掌握JavaScript的继承机制

您所在的位置:网站首页 rollingdown什么意思 JS原型和原型链:一文掌握JavaScript的继承机制

JS原型和原型链:一文掌握JavaScript的继承机制

#JS原型和原型链:一文掌握JavaScript的继承机制| 来源: 网络整理| 查看: 265

## 什么是原型? 在JavaScript中,每个函数都有一个属性叫做prototype,它指向一个对象,这个对象就是该函数的**原型对象**。 原型对象中有一个属性叫做constructor,它指向该函数本身。这样就形成了一个循环引用的关系。 function Foo() { // ... } console.log(Foo.prototype); // Foo 的原型对象 console.log(Foo.prototype.constructor); // Foo console.log(Foo.prototype.constructor === Foo); // true 那么为什么要有原型对象呢?原型对象的作用是存放一些公共的方法或属性,供该函数创建的实例对象共享使用。例如: function Person(name, age) { this.name = name; this.age = age; } Person.prototype.sayHello = function() { console.log("Hello, I'm " + this.name); }; var p1 = new Person("Alice", 20); var p2 = new Person("Bob", 22); p1.sayHello(); // Hello, I'm Alice p2.sayHello(); // Hello, I'm Bob console.log(p1.sayHello === p2.sayHello); // true

在上面的例子中,我们定义了一个Person构造函数,并给它的原型对象添加了一个sayHello方法。然后我们用new操作符创建了两个Person实例对象p1和p2。这两个实例对象都可以调用sayHello方法,并且这个方法其实是同一个函数,在内存中只存在一份。

什么是原型链?

我们已经知道了每个函数都有一个原型对象,那么每个对象呢?其实每个对象也有一个属性叫做__proto__(注意前后都有两个下划线),它指向该对象的原型。那么这个原型又是什么呢?其实就是该对象所属构造函数的prototype属性所指向的那个原型对象。

function Foo() { // ... } var f = new Foo(); console.log(f.__proto__); // f 的原型 console.log(f.__proto__ === Foo.prototype); // true 在上面的例子中,我们用Foo构造函数创建了一个f实例对象。f.__proto__就指向了Foo.prototype,也就是f的原型。 那么为什么要有__proto__属性呢?__proto__属性的作用是在访问一个对象的某个属性或方法时, 如果在该对象本身没有找到,则会沿着__proto__属性向上查找,直到找到或者到达null为止。 这样就形成了一条链式结构,称为原型链。 function Person(name) { this.name = name; } Person.prototype.sayName = function() { console.log(this.name); }; var p = new Person("Tom"); p.sayName(); // Tom // 实际上执行了以下步骤: // 1. 查找 p 对象是否有 sayName 属性,没有则继续; // 2. 查找 p.__proto__ 即 Person.prototype 是否有 sayName 属性, // 找到则调用并返回结果; // 如果没有则继续; // 3. 查找 p.__proto__.__proto__ 即 Object.prototype 是否有 sayName 属性, // 如果没有则继续; // 4. 查找 p.__proto__.__proto__.__proto__ 即 null 是否有 sayName 属性, // 因为 null 没有任何属性,所以查找结束,返回 undefined。

原型链的作用是实现JavaScript的继承。继承是指一个对象可以拥有另一个对象的属性或方法。例如:

function Animal(name) { this.name = name; } Animal.prototype.eat = function() { console.log(this.name + " is eating."); }; function Dog(name) { Animal.call(this, name); // 借用父类构造函数,实现属性继承 } Dog.prototype = Object.create(Animal.prototype); // 设置子类原型为父类原型的副本,实现方法继承 Dog.prototype.constructor = Dog; // 修正子类原型的构造函数指向 Dog.prototype.bark = function() { console.log(this.name + " is barking."); }; var d = new Dog("Spot"); d.eat(); // Spot is eating. d.bark(); // Spot is barking. console.log(d instanceof Dog); // true console.log(d instanceof Animal); // true

在上面的例子中,我们定义了一个Animal构造函数,并给它的原型对象添加了一个eat方法。然后我们定义了一个Dog构造函数,并让它继承自Animal。这样我们就可以创建一个Dog实例对象d,并让它拥有Animal的属性和方法,以及自己特有的bark方法。

总结原型是一种设计模式,用于创建重复的对象,并保证性能;原型对象是每个函数创建时自动生成的一个对象,存放一些公共的方法或属性;原型链是每个对象通过__proto__属性向上查找自己原型的过程,用于实现继承;继承是一种机制,让一个对象可以拥有另一个对象的属性或方法。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3