引言
从创建一个函数开始,了解函数与函数的prototype,以及对象实例三者之间形成的原型链关系。
一、创建函数
function CreateCar(){}
console.log(CreateCar);
//function CreateCar(){}
上面我们创建了一个函数,直接打印函数名,得到的结果是函数本身,好像并没有其他的属性。但实际上,只要函数被创建,函数就会默认的添加一个隐形的prototype属性。
function CreateCar(){}
console.log(CreateCar.prototype);
//{constructor: function CreateCar(){}}
打印CreateCar.prototype,得到的结果是一个对象,这个对象就是函数的原型对象。
二、原型对象
原型对象初始只有一个constructor属性,这个属性的值指向的是函数本身。
function CreateCar(){};
console.log(CreateCar.prototype.constructor === CreateCar);
//true
原型对象有什么用呢,现在好像看不出来啥,我们把函数当构造函数用试试:
function CreateCar(){};
let car = new CreateCar();
console.log(car);
//{}
console.log(car.varieties)
//undefined
可以看到,创建出来的是个空对象,并且调用对象没有的属性时返回的是undefined,接着对函数的原型对象prototype一顿操作:
function CreateCar(){};
CreateCar.prototype.varieties = '小车';
let car1 = new CreateCar();
console.log(car1);
//{}
console.log(car1.varieties);
//小车
let car2 = new CreateCar();
console.log(car2);
//{}
console.log(car2.varieties);
//小车
创建的对象car1和car2都是空对象,但是打印它们的varieties都有值且都为'小车',可以明显发现,函数原型对象prototype上的属性,是函数作为构造函数时创建出的对象所共有的。但为什么car1和car2都是空对象,但是却都可以打印出varieties的值呢?这就和原型链扯上关系了。
三、原型链
首先,我们知道一个构造函数创建出来的对象,对象上的属性是由函数体内的语句定义的。这些属性我们可以直接看见并打印,请看如下示例。
function CreateCar(color){
this.color = color;
};
let car1 = new CreateCar('白色');
console.log(car1);
//{color: "白色"}
let car2 = new CreateCar('黑色');
console.log(car2);
//{color: "黑色"}
然后我们已经知道,函数的原型对象上的属性,虽然在对象上看不到,但是会被所有该函数创建出来的对象公用,看如下示例。
function CreateCar(color){
this.color = color;
};
CreateCar.prototype.varieties = '小车';
console.log(CreateCar.prototype);
//{varieties: "小车", constructor: function CreateCar(color){this.color = color;}}
let car1 = new CreateCar('白色');
console.log(car1);
//{color: "白色"}
console.log(car1.varieties);
//小车
let car2 = new CreateCar('黑色');
console.log(car2);
//{color: "黑色"}
console.log(car2.varieties);
//小车
console.log(car2.numberOfwheels);
//undefined
varieties属性虽然不在对象内展示,但是car1和car2都可以打印出来,这是因为打印varieties的时候,car1和car2都会先在自己身上找varieties,找不到就会去自己构造函数CreateCar的prototype上找(通过__proto__建立关系),找到了就打印出来。而打印car2.numberOfwheels时候,同样car2首先会在自身找,找不到就去构造函数CreateCar的prototype上找,这时候找不到还会继续向上去原生构造函数Object的prototype上找,此时还找不到,就返回undefined了,下面图示这一系列关系。
那如果对象自身属性和原型对象中属性重名会怎样
function CreateCar(){
this.varieties = '大车'
};
CreateCar.prototype.varieties = '小车';
let car = new CreateCar();
console.log(car);
//{varieties: "大车"}
可以看到,会优先打印就近找到的属性值。
总结
- 每个函数都有一个原型对象prototype。
- 函数原型对象prototype上的属性会被所有该函数创建出来的对象公用。
- 调用对象某个值,寻找顺序为:对象自身 → 对象构造函数的prototype → 原生构造函数的prototype → null,这条链即为原型链。
- 当对象自身属性和构造函数原型对象的属性重名时,会优先打印就近找到的属性值。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!