JS-原型&原型链
JS-原型&原型链
JavaScript 的对象模型是基于原型的,这句话意味着 JavaScript 中的对象不是通过类来定义和继承的(如 Java 或 C++),而是通过一个称为“原型”的机制来进行属性查找和行为(方法)共享的
在js中,任何函数在被new关键字修饰函数后,就成为构造函数了,所以任何函数都有成为构造函数的可能
在js中,函数本身即对象,所以prototype是函数特有的属性
prototype&_proto_
prototype是某一个构造函数实例化的所有对象可以找到公共的方法和属性,这个属性的设计之初,就是为了实现对象方法和属性的集成
__proto__属性是一个构造函数实例化成为对象后存在的属性
var Parent = function(){
}
var instance = new Parent();
Parent.prototype.name = "所有Parent的实例都可以读取到我";
let p1 = new Parent();
let p2 = new Parent();
p1.name //"所有Parent的实例都可以读取到我";
p2.name //"所有Parent的实例都可以读取到我";
在这里,Parent在实例化为p1对象之前,通过这个方法的属性prototype,增加了一个name属性(还可以增加其他的属性或者方法)
但实例化p1对象之后,p1对象存在一个属性_proto_,这个属性等于其构造函数的prototype属性
当p1.name被执行时,首先寻找p1对象中是否存在这个name属性,如果不存在则找到_proto_,也就是找到其构造函数的prototype属性(他也是一个对象)
从中寻找到被添加的name属性
原型链
每个对象都有一个内部链接([[Prototype]]
),它指向另一个对象,这个被链接的对象就是我们所说的“原型”。当尝试访问一个对象的属性时,如果该对象本身没有这个属性,JavaScript 引擎会沿着这条 [[Prototype]]
链向上查找,直到找到该属性或到达原型链的末端(即 null
),因为 null
表示没有更多的原型可以访问。
构造函数与原型
当你使用构造函数创建对象时,构造函数有一个名为 prototype
的属性,它是一个对象,所有由该构造函数创建的实例都会将它们的内部 [[Prototype]]
指向这个 prototype
对象。因此,这些实例共享了原型上的属性和方法。
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log("Hello, " + this.name);
};
let person1 = new Person('Alice');
person1.sayHello(); // 输出: Hello, Alice
在这个例子中,person1
的 [[Prototype]]
指向 Person.prototype
,所以它可以访问 sayHello
方法,即使该方法并没有直接定义在 person1
上。
动态特性
由于原型链的存在,JavaScript 对象是动态的,这意味着你可以在运行时添加、修改或删除对象的属性和方法,甚至改变原型链。例如,你可以随时向原型添加新的方法,所有已经存在的实例也会立即获得这些新方法。
// 给原型添加一个新的方法
Person.prototype.sayGoodbye = function() {
console.log("Goodbye, " + this.name);
};
person1.sayGoodbye(); // 输出: Goodbye, Alice