原型是 JavaScript 对象相互继承特性的机制。
JavaScript 中所有的对象都有一个内置属性,称为它的 [[prototype]](原型)。它本身是一个对象,所以叫做原型对象,原型对象也会有它自己的原型,逐渐构成了原型链。原型链终止于拥有 null 作为其原型的对象上 (Object.prototype)。
当你试图访问一个对象的属性时:如果在对象本身中找不到该属性,就会在原型中搜索该属性。如果仍然找不到该属性,那么就搜索原型的原型,以此类推,直到找到该属性,或者到达链的末端,在这种情况下,返回 undefined。
Object.prototype 是最基础的原型,所有对象默认都拥有它。Object.prototype 的原型是 null
一个对象的原型并不总是 Object.prototype
获取原型
Object.getPrototypeOf__proto__p.constructor.prototype
对象内置属性 [[prototype]]
- Get 操作
- for in
属性设置屏蔽
[[prootype]] 上是否存在属性
如果你在一个对象中定义了一个属性,而在该对象的原型中定义了一个同名的属性就会出现属性屏蔽
- 存在
- 不是只读,创建屏蔽属性
- 只读
writable:false, 无法创建修改已有属性 setter无法创建修改setter
- 不存在
- 创建屏蔽属性
检查一个对象的继承祖先(内省或者反射)
-
object instanceof constructor只能处理对象和函数关系
-
isPrototypeOf(object)
设置原型
使用 Object.create
Object.create(obj) 来创建一个以 obj 为原型的新对象
const personPrototype = {
greet() {
console.log("hello!");
},
};
const carl = Object.create(personPrototype);
carl.greet(); // hello!
使用构造函数
所有的函数(除了内置函数)都有一个名为 prototype 的属性不可枚举。当你调用一个函数作为构造函数时,这个属性被设置为新构造对象的原型
因此,如果我们设置一个构造函数的 prototype,我们可以确保所有用该构造函数创建的对象都被赋予该原型
const personPrototype = {
greet() {
console.log(`你好,我的名字是 ${this.name}!`);
},
};
function Person(name) {
this.name = name;
}
Object.assign(Person.prototype, personPrototype);
// 或
// Person.prototype.greet = personPrototype.greet;
const reuben = new Person("Reuben");
reuben.greet(); // 你好,我的名字是 Reuben!
函数原型
使用 new 调用构造函数
- 新对象
[[prototype]]指向函数的prototype - 新对象
constructor委托给函数的prototype
函数的 prototype
普通函数默认有一个公有并且不可枚举的属性 constructor
函数之间委托
-
Bar.prototype = Object.create(Foo.prototype)创建一个新对象并把新对象内部的
[[Prototype]]关联到你指定的对象 -
Bar.prototype = Foo.prototype- Bar.prototype 直接引用 Foo.prototype对象
- 相互影响
-
Bar.prototype = new Foo()- Foo 的额外功能会影响 Bar
-
Object.setPrototypeOf(..)
创建关联
Object.create(null)instanceof总会返回false
- 内部委托