含义
原型链是一个用于连接 JavaScript 对象实例与其原型对象的机制。每个 JavaScript 对象都有一个内部指针(称为 [[Prototype]]),指向它的原型对象。当试图访问某个对象的属性时,JavaScript 引擎会先在该对象自身的属性中查找,如果没有找到,则会在其原型对象中查找,依此类推,直到找到属性或到达原型链的尽头(即原型为 null)为止。
查找对象原型的方法
let obj = new Object();
console.log(Object.getPrototypeOf(obj)); // 输出:Object {}
console.log(obj.__proto__); // 输出:Object {}
每个构造函数(如 function Dog() {})都有一个原型对象(Dog.prototype),并且所有由该构造函数创建的对象都会继承该原型对象。构造函数的原型对象也有一个 constructor 属性,该属性指向构造函数本身,从而形成了一个闭环。
function Dog(name) {
this.name = name;
}
let dog = new Dog("Rex");
console.log(dog.constructor); // 输出:ƒ Dog(name) { this.name = name; }
console.log(Dog.prototype.constructor); // 输出:ƒ Dog(name) { this.name = name; }
原型链继承
// 定义父类
function Animal(kind) {
this.kind = kind;
}
Animal.prototype.describe = function() {
console.log('This is an ' + this.kind + '.');
};
// 定义子类
function Dog(kind, breed) {
// 继承父类的属性和方法
Animal.call(this, kind);
this.breed = breed;
}
// 创建子类的原型
Dog.prototype = Object.create(Animal.prototype);
// 修复构造函数
Dog.prototype.constructor = Dog;
// 添加子类特有的方法
Dog.prototype.sayBark = function() {
console.log('Woof woof!');
};
在这个例子中,我们首先定义了一个名为 Animal
的父类,并为其添加了一个 describe()
方法。然后,我们定义了一个名为 Dog
的子类,它有一个构造函数,该构造函数在初始化新创建的对象时调用。在构造函数中,我们使用 call()
方法调用父类的构造函数,并将 this
设置为当前正在创建的新对象。这样,我们就在新创建的对象上继承了父类的属性和方法。 接下来,我们将子类的原型设置为父类原型的一个副本,这使得所有的实例都可以共享父类的方法。但是,这样也会导致子类的原型上的 constructor
属性被更改,所以我们需要重新设置它,使其指向子类。 最后,我们在子类的原型上添加了一个 sayBark()
方法,这是子类独有的方法。
这样,我们就实现了从 Animal
类到 Dog
类的原型链继承。现在我们可以像这样创建并使用 Dog
实例:
var myDog = new Dog('dog', 'Labrador');
myDog.describe(); // 输出: This is a dog.
myDog.sayBark(); // 输出: Woof woof!
总结
var obj={}; //普通对象
function fun(){}; //fun叫函数对象
fun.prototype; // 原型对象
var obj={}; 是一种创建对象的语法糖,其本质是var obj=new Object();
定义一个函数 function fun(){},也是语法糖 其实质是调用var fun=new Function();
其实Object是一个函数对象 因为他也是Function创建的,所以可以说 普通对象是由函数对象创建的,函数对象是由Function创建;原型对象是伴随函数对象创建而产生的。
函数对象一定有两个自有属性 prototype 和__proto__
原型对象一定有两个constructor,__proto__属性
普通对象一定有 一个 __proto__自有属性
普通对象的隐式原型__proto__指向创建者的的原型prototype 属性 ,即完全相等
原型对象的prototype.constructor指向伴随着产生他的创建者,即完全相等