JavaScript 中除了基础类型外的数据类型,都是对象(引用类型)。但是由于其没有 类(class,ES6 引入了 class,但其只是语法糖)的概念,如何将所有对象联系起来就成立一个问题,于是就有了原型和原型链的概念。
每个实例对象( object )都有一个私有属性(称之为 proto )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( proto ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。
理解原型的几个关键点
1、所有的引用类型(数组、函数、对象)可以自由扩展属性(除null以外)。
2、所有的引用类型都有一个__proto__属性(也叫隐式原型,它是一个普通的对象)。
3、所有的函数都有一个’prototype’属性(这也叫显式原型,它也是一个普通的对象)。
4、所有引用类型,它的__proto__属性指向它的构造函数的’prototype’属性。
5、当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,那么就会去它的__proto__属性(也就是它的构造函数的’prototype’属性)中去寻找。
下面通过一个简单的列子来说明一下
function fun(name,age) {
this.name = name;
this.age = age;
}
function test() {
var a1= new fun("张三","18");
var a2 = new fun("李四","19");
Man.prototype.sex = "男";
console.log(a1.sex); //男
console.log(a2 .sex); //男
}
在js中函数也是一个对象。每个函数都有一个prototype属性(只有函数才有prototype属性),这是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。按照字面意思来理解,那么prototype就是通过调用构造函数而创建的那个对象实例的原型对象。其中原型对象会自动获得一个constructor属性,这个属性指向prototype属性所在的指针。如上面的fun.prototype.constructor指向fun。
每个男孩共有的属性就是他的性别都是男,所以我们可以将此属性添加到实例的原型对象中去。这样每个实例都可以共享这个属性。