每个函数都会创建一个 prototype 属性, 这个属性是一个对象, 包含应该由特定引用类型的实例共享的属性和方法。 实际上,这个对象就是通过调用构造函数创建的对象的原型。
使用原型对象的好处是, 在它上面定义的属性和方法可以被对象实例共享。 原来在构造函数中直接赋值给对象实例的值, 可以直接赋值给它们的原型, 如下所示:
function Person() {
}
Person.prototype.name = "Jin";
Person.prototype.age = 18;
Person.prototype.jon = "Software Engineer";
Person.prototype.sayNmae = function () {
consoel.log(this.name)
}
let person1 = new Person();
let person2 = new Person();
person1.sayName(); //Jin
person2.sayName(); //Jin
console.log(person1.sayName == person2.sayName ); // true
在上述例子送, 所有的属性以及 sayName() 方法都直接添加到了 Person 的 prototype 属性上,而构造函数体中什么也没有。这样子定义以后, 调用构造函数创建的新对象仍然拥有相应的属性和方法。与构造函数模式不同, 使用这种原型模式定义的属性和方法是由所有实例共享的。 因此 person1 和 person2 访问的都是相同的属性和相同的 sayName() 函数。
理解一下ECMAScript 中的原型
理解原型
不论何时,只要创建一个函数, 就会按照特定的规则为这个函数创建一个 prototype 属性 (指向原型对象)。 默认情况下, 所有原型对象会自动获得一个名为 constructor 的属性, 指回与之关联的构造函数。例如, Person.prototype.constructor 就指向 Person。
在我们自定义一个构造函数的时候, 原型对象默认只会获得 constructor 属性, 其他的所有方法都继承自 Object。 每次调用构造函数创建一个新的实例的时候, 这个实例内部的 [[Prototype]] 指针就被赋值为构造函数的原型对象。 脚本中没有访问这个 [[ Prototype ]] 特性的标准方式, 但是在 Firefox, Safari 和 Chrome 中会在每个对象上暴露__ proto__ 属性, 通过这个属性可以访问对象的原型。 主要理解的一点是, 实例与构造函数的原型之间有着直接的联系, 但实例和构造函数之间没有。
举个🌰 :
1、创建一个构造函数
function Person() {
} // 声明一个构造函数
let Person = function() {
} // 或者使用函数声明创建
2、这个构造函数就有了一个与之管理的原型对象 Person.prototype
console.log(Person.prototype)
// {
// constructor: ƒ Person()
// [[Prototype]]: Object
// }
3、这个原型对象有个constructor属性指回构造函数, Object原型的原型是null
console.log(Person.prototype.constructor == Person); //true
4、正常的原型链都会终止于 Object 的原型对象
console.log(Person.prototype.__proto__ === Object.prototype); //true
console.log(Person