自己的话:
你是否看过很多关于javascript的原型,和原型链的技术文章?但是看完后仍然是一头雾水?
没关系,希望我的这一篇文章,能让你一看就懂。
原型和原型链是JavaScript实现继承和共享属性的重要机制。
每个JavaScript对象都有一个内部属性 [[Prototype]],这个属性指向另一个对象,这个对象被称为“原型”。
比如:
const Myobj = {
name: "John",
age: 30,
city: "New York"
};
console.log(Myobj);
输出结果:
(注意我用红框高亮的部分,分别是
prototype (显示为Object),其包含了 --> 【构造函数constructor】 以及 【__proto__】
当你访问一个对象的属性或方法时,JavaScript首先会查找该对象自身是否具有这个属性或方法。如果没有,它将查找该对象的原型,而原型对象可能也有原型,于是一层一层(通过__proto__作为桥梁),依此类推,直到找到或者到达原型链的末端(通常是 null)
接下来我们详细讲解:
1.prototype
prototype 是一个对象,用于存储构造函数创建的所有实例所共享的属性和方法。
作用:通过 prototype,我们可以给构造函数添加属性和方法,使得所有由该构造函数创建的对象实例都能访问这些属性和方法。并且实现类的继承。
示例
function Father() {
this.fatherProperty = '我是父类属性';
}
//添加方法
Father.prototype.fatherMethod = function() {
console.log('我是父类方法');
};
function Child() {
this.childProperty = '我是子类属性';
}
// 继承父类的属性和方法
Child.prototype = new Father();
Child.prototype.constructor = Child;
const childInstance = new Child();
console.log(childInstance.fatherProperty); // 输出: '我是父类属性'
childInstance.fatherMethod(); // 输出: '我是父类方法'
2. __proto__
每当我们使用构造函数创建一个新对象时,这个新对象会有一个 __proto__ 属性指向构造函数的 prototype 属性
作用:通过 __proto__,我们可以直接访问或修改对象的原型,但是这种做法并不推荐,因为可能会破坏继承链
例如下面的代码,两个对象A和B,原本没有继承关系,但可以通过__proto__让其互相访问属性
const A = {
eats: true
};
const B = {
drink: true
};
// 设置 B 的原型为 A
B.__proto__ = A;
console.log(B.eats); // 输出: true,来源于 A
console.log(B.__proto__ === A); // 输出: true
总结:
prototype 与构造函数相关,用于为所有实例提供共享的属性和方法。
__proto__ 与对象实例相关,它指向了构造函数的 prototype,用于访问具体对象的原型。