一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第2天,点击查看活动详情。
原型和原型链是js中的一个非常重要的概念,那什么是原型和原型链呢?
原型
在js中,每一个函数都会自带一个prototype属性,这个属性指向的就是该函数的原型,我们来看个例子:
看下图中的obj和fn有没有什么区别,fn有一个属性prototype,obj中是没有的,因为prototype是函数所独有的。
原型链
每一个对象都有一个属性_proto_,还是上图,我们注意到obj和fn中都有一个[[Prototype]],[[Prototype]]其实是_proto_的另一种表现形式。那什么是原型链呢?
我们先来写一个函数
function Person(){}
注意哦,不要以为我这边的Person是首字母大写的就是构造函数哦,它现在还不是。我们往它原型上挂一些属性和方法。
function Person(){};
Person.prototype.name = "张三";
Person.prototype.age = 18;
Person.prototype.getAge = function() {
console.log(this.age);
}
console.dir(Person)
看下控制台
Person现在有了age,getAge,name,再来
function Person(){};
Person.prototype.name = "张三";
Person.prototype.age = 18;
Person.prototype.getAge = function() {
console.log(this.age);
}
let person1 = new Person();
console.log(person1.getAge());
person1取到了age 18,其实当我new了一个Person之后,此时的Person才能真正地被称为构造函数,现在person1就是Person的一个实例,他们之间形成了一种继承关系。
function Person(){};
Person.prototype.name = "张三";
Person.prototype.age = 18;
Person.prototype.getAge = function() {
console.log(this.age);
}
let person1 = new Person();
person1.grade = 98;
console.log(person1.grade);
现在我给person1自己定义了一个属性叫grade
OK,成功取到了grade 98,那现在我如果想知道grade到底是person1的还是Person的怎么办呢,继续看~
function Person(){};
Person.prototype.name = "张三";
Person.prototype.age = 18;
Person.prototype.getAge = function() {
console.log(this.age);
}
let person1 = new Person();
person1.grade = 98;
console.log(person1.grade);
function Person(){};
Person.prototype.name = "张三";
Person.prototype.age = 18;
Person.prototype.getAge = function() {
console.log(this.age);
}
let person1 = new Person();
person1.grade = 98;
for(let item in person1){
if(person1.hasOwnProperty(item)){
console.log(item);
}
}
取到了grade,证明grade是它的自有属性,那有人又要问了,hasOwnProperty这个方法哪儿来的呢,person1没有,Person也没有,把person1打印出来看一下
在顶层的构造函数Object那儿找到了。
当我们找一个函数的属性的时候,当前函数中找不到,就会去它的父级找,父级再找不到就去它父级的父级找,一直找到null,如果还找不到就会抛出undefined。顺着这条链一层一层往上找的过程,这条链就称为“原型链”。
我经常举的一个例子,原型和原型链其实就好比人类的一个遗传机制,你,你的父亲,你的祖父,你的曾祖父,直到你的第一代祖宗,而这第一代祖宗就是原型,这条基因链就是原型链。