前言
距离上次写文章,时隔一年。此次的目的,整理文章,强化记忆,为以后巩固留下笔记。
构造函数
构造函数与其他函数的唯一区别,就在于他们调用的方式不同。
任何函数只要通过new
操作符来调用,那他就可以称之为构造函数。
下面来创建一个构造函数:
function Animal() {
}
var animal = new Animal();
console.log(animal.name); // undefined
上述代码中,我们通过new
操作符创建了一个实例对象animal。
Animal.prototype.name = 'jerry';
var animal1 = new Animal();
var animal2 = new Animal();
console.log(animal1.name,animal2.name);// jerry,jerry
原型
什么是原型?
我们创建的每一个函数,都有一个prototype
属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。
简单来说,就是通过构造函数而创建的那个对象实例的原型对象
。

__ proto __
Animal.prototype.name = 'jerry';
console.log(animal.name); // 'jerry';
上述代码中,我们对prototype
进行赋值,打印animal
得到jerry
。
那么animal
和Animal
是什么关系呢?
console.log(animal.__proto__ === Animal.prototype)// true
从而我们可以得知下图关系

为什么我们没有给animal.name 进行赋值,也能得到值呢?
Animal.prototype.name = 'jerry';
animal.name = 'tom';
console.log(animal.name); // 'tom';
delete animal.name;
console.log(animal.name);//jerry;
当我们给animal.name
进行赋值,得到tom,当我们删除了animal.name
,得到了jerry。
它们之间是不是还含有更深的关联关系呢。
Animal.prototype.name = 'jerry';
Object.prototype.name = 'person';
animal.name = 'tom';
console.log(animal.name); // 'tom';
delete animal.name;
console.log(animal.name);//jerry;
delete Animal.prototype.name;
console.log(animal.name);//person;
原型的原型
console.log(animal.__proto__.__proto__ === Object.prototype);//true
由此我们可以得知为什么当没有对animal进行赋值时,同样可以获取到值。
这里通过一层一层的隐式原型去查找animal.name
返回,否则返回undefined
。

constructor
现在我们已经知道Animal的原型是Animal的原型对象,那我们可以从原型对像中得到其构造函数吗?
console.log(Animal.prototype.constructor === Animal);//true
console.log(Object.prototype.constructor === Object) //true
由于构造函数都可以通过new得到多个实例对象,所以只能通过constructor
得到构造函数,无法获取其他实例对象,因此我们来补充其关系图。

原型链
此时我们已经知道了Object的原型是Object.prototype的原型对象,那么,Object.prototype的隐式原型__proto__是什么?
Object.prototype.__proto__ === null //true
现在我们已经可以总结出原型链的具体关系了。

上图的红色线条所关联的链路就是原型链
相关资料
《JavaScript高级程序设计》