一、原型的介绍
原型是JavaScript中function对象的一个属性,它定义了构造函数制造出的对象的公共祖先,通过该构造函数产生的对象,可以继承该原型的属性和方法,原型也是对象。
二、原型的使用
prototype
JavaScript中每一个函数都有一个属性:prototype,这个属性是在函数生成后系统自带的属性,并且每个对象都可以获取到原型中的属性。
<script type="text/javascript">
function Student(){
}
var stu = new Student();
Student.prototype.name = 'Jerry';/*如果prototype中没有这个属性,在这个语句后也会生成相应属性*/
console.log(stu.name);/*输出Jerry*/
</script>
同样的,不仅仅是属性,方法也是可以继承的:
<script type="text/javascript">
function Student(){
}
var stu = new Student();
Student.prototype.sayHello = function (){
console.log('hello');
};
stu.sayHello();/*调用方法后输出hello*/
</script>
但是如果当我们在构造函数中拥有和原型一样的属性或者方法的时候,会优先使用构造函数的属性和方法:
<script type="text/javascript">
function Student(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
this.sayHello = function (){
console.log("hello I'm", name);
}
}
var stu = new Student('Tom', 18, 'male');
Student.prototype.sayHello = function (){
console.log('hello');
};
stu.sayHello();/*调用sayHello方法*/
console.log(stu.name);/*输出名字*/
</script>
运行结果如下:
利用原型的这个特征,我们就可以把一些对象的共有属性提取出来:
<script type="text/javascript">
Student.prototype.school = '清华大学';
Student.prototype.country = '中国';
function Student(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
}
var stu1 = new Student('Tom', 18, 'male');
var stu2 = new Student('Jerry', 20, 'female');
console.log(stu1.school, stu1.country, stu1.name, stu1.age, stu1.sex);
console.log(stu2.school, stu2.country, stu2.name, stu2.age, stu2.sex);
</script>
运行结果:
设置共有属性还有一种更简便的方法:
Student.prototype = {
school : '清华大学',
country : '中国'
}
效果和上述代码一样。
constructor
在原型的使用中,我们还会遇到一个属性,constructor,它是用于查看对象的构造器的属性,并且这个属性也是系统自带的,我们也可以对其进行修改:
<script type="text/javascript">
function Student(){
}
var stu = new Student();
console.log(stu.constructor);
</script>
运行结果:
进行修改:
<script type="text/javascript">
function Student(){
}
var stu = new Student();
stu.constructor = function Teacher(){
};
console.log(stu.constructor);
</script>
运行结果:
proto
在上面的运行结果截图中,我们可以看到,对象还有一个自带的属性_proto_,这个属性代表的是当前对象的构造器所指向的原型,具体使用如下:
<script type="text/javascript">
function Country(){
name = 'China';
}
function Province(){
place = 'Fu Jian';
}
function City(){
detail = 'Xia Men';
}
City.prototype = Province;
Province.prototype = Country;
var city = new City();
var province = new Province();
var country = new Country();
</script>
结果如下:
三、原型链
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念。
上面是博主看到的有关于原型链的概念,其实原型链可以理解成一个构造器连接着上一层的实例,上一层的实例接着往上连接,以此类推,就形成了原型链,具体的示例如下:
<script type="text/javascript">
function Grand(){
this.getGrand = 'grand';
}
var grand = new Grand();
Father.prototype = grand;
function Father(){
this.getFather = 'father';
}
var father = new Father();
Son.prototype = father;
function Son(){
this.getSon = 'son';
}
var son = new Son();
</script>
就好比上述代码,就是形成了一条原型链,Son的原型是已经实例化的father对象,Father的原型是已经实例化的grand对象,那么实例化的son就可以调用Grand构造器和Father构造器中的属性,而相反地,实例化的father就无法调用Son构造器中的方法或属性,实例化的grand同理,测试结果:
这里我们还可以看到,每一个对象的最顶层都有一个object对象,可以说绝大多数对象都继承自object对象,也就是原型链的顶端就是object对象:
上述提到了大多数对象都会继承于object,但是有一个例外,这里要介绍另一个创建原型的方法,object.create(原型/null);具体使用如下:
<script type="text/javascript">
var obj = Object.create(null);
</script>
可以很明显地看出,这里的obj没有任何的属性,也就是并不继承于object,但是obj仍然是个对象:
最后再简要地介绍一下有关于原型属性的一些增加、删除的方法,这里主要在控制台测试,基础代码依旧如下:
<script type="text/javascript">
function Grand(){
this.getGrand = 'grand';
}
var grand = new Grand();
Father.prototype = grand;
function Father(){
this.getFather = 'father';
}
var father = new Father();
Son.prototype = father;
function Son(){
this.getSon = 'son';
}
var son = new Son();
</script>
可以看出,上述代码中并没有name的属性,这里在控制台中添加一下:
son的_proto_就增加了name的属性并进行了赋值,删除的话如下:
这里就成功地把刚刚添加的name属性进行了删除。
关于原型和原型链的内容这边就简单介绍到这里啦,如果有不对的地方希望大家帮博主指出来一下哦,蟹蟹大家!