什么是构造函数,什么是实例
- 构造函数是对一个实例的一个描述
- 构造函数 ,是一种特殊的方法。主要用来
在创建对象时初始化对象
, 即为对象成员变量赋初始值
,总与new运算符一起使用在创建对象的语句中
。特别的一个类可以有多个构造函数,可根据其参数个数的不同或参数类型的不同来区分它们 即构造函数的重载
。
function Person (name){
this.name = name;
}
var xiaoming = new Person('小明');
var xiaohong = new Person('小红');
console.log(xiaoming);
console.log(xiaohong);
- 这里的Person就是一个类,也是一个构造函数
- 这里的xiaoming,跟xiaohong 都是一个实例,通过new一个构造函数去实例化出来的对象
构造函数是一个方法,所以,在new的过程中会执行
function Person (name){
console.log(name+'在new的过程中执行了')
this.name = name;
}
var xiaoming = new Person('小明');
var xiaohong = new Person('小红');
console.log(xiaoming);
console.log(xiaohong);
this.name 就是在构造函数中,声明的一个属性
function Person (name,age){
//console.log(name+'在new的过程中执行了')
this.name = name;
this.age = age;
}
var xiaoming = new Person('小明',18);
var xiaohong = new Person('小红',16);
console.log(xiaoming);
console.log(xiaohong);
以上是构造函数简单的介绍,接下来讲什么是原型
每个构造函数都有一个原型属性,prototype
这个原型属性怎么用?
其实,原型的属性,就是对构造函数的一个描述
我们可以尝试打印,在浏览器看看它是什么样子的
function Person (name,age){
//console.log(name+'在new的过程中执行了')
this.name = name;
this.age = age;
}
var xiaoming = new Person('小明',18);
var xiaohong = new Person('小红',16);
console.log(xiaoming);
console.log(xiaohong);
console.log(Person.prototype)
浏览器显示结果
可以发现它是一个对象
我们试着给这个Person类添加一些描述
例如一个人,它会说话
function Person (name,age){
//console.log(name+'在new的过程中执行了')
this.name = name;
this.age = age;
}
Person.prototype.say = function() {
console.log(this.name + 'say hello world')
}
var xiaoming = new Person('小明',18);
var xiaohong = new Person('小红',16);
xiaoming.say();
console.log(xiaoming);
console.log(xiaohong);
console.log(Person.prototype)
说明,在构造函数的prototype
里面的属性,实例
都会拥有,并且能使用
那么这个prototype被写入了属性之后,它长什么样子
function Person (name,age){
//console.log(name+'在new的过程中执行了')
this.name = name;
this.age = age;
}
Person.prototype.say = function() {
console.log(this.name + 'say hello world')
}
Person.prototype.work = function() {
if(this.age < 18){
console.log('未成年')
} else {
console.log('已成年')
}
}
console.log(Person.prototype)
浏览器显示结果
它是一个对象
然后,我们仔细看,实例里面的属性
function Person (name,age){
//console.log(name+'在new的过程中执行了')
this.name = name;
this.age = age;
}
Person.prototype.say = function() {
console.log(this.name + 'say hello world')
}
Person.prototype.work = function() {
if(this.age < 18){
console.log('未成年')
} else {
console.log('已成年')
}
}
// console.log(Person.prototype)
var xiaoming = new Person('小明',18);
var xiaohong = new Person('小红',16);
console.log(xiaoming)
这里,我们打印一下这个实例,浏览器显示结果
我们发现在实例的本身属性中,是没有say跟work这两个属性的
那它是怎么调用得到的呢
我们看到有个__proto__
这个对象,我们展开它看到
这里,我们就猜测出了,在类的prototype的属性,被实例化后,都跑到了实例的__proto__里面了
因为实例化之后,它是一个对象,所以,我们可以对这个对象进行操作
我们修改一下小明的年龄
function Person (name,age){
//console.log(name+'在new的过程中执行了')
this.name = name;
this.age = age;
}
Person.prototype.say = function() {
console.log(this.name + 'say hello world')
}
Person.prototype.work = function() {
if(this.age < 18){
console.log('未成年')
} else {
console.log('已成年')
}
}
// console.log(Person.prototype)
var xiaoming = new Person('小明',18);
var xiaohong = new Person('小红',16);
//我们修改一下小明的年龄
xiaoming.age = 22;
xiaoming.work();
console.log(xiaoming);
console.log(xiaohong);
可以看到,我们可以单独的去修改,每个实例的内容
我们再尝试修改一下实例的__proto__吧
我们给小明新增一个sleep的方法
//我们给小明新增一个sleep的方法
var xiaoming = new Person('小明',18);
var xiaohong = new Person('小红',16);
//我们给小明新增一个sleep的方法
xiaoming.__proto__.sleep = function(){
console.log('go to sleep')
}
console.log(xiaoming);
console.log(xiaohong);
你会发现小红也有了这个方法
于是,我们猜测
构造函数的prototype
里的东西,是每个实例同时共享的
回到我们的问题上
问:为什么说属性在构造函数中声明,方法在原型中声明
答:因为在构造函数中声明后,通过new关键字实例化出来的实例都是单独享有,
所以,属性在构造函数中声明
。因为方法大家都是共用的,而且不经常改变,所以,方法可以在prototype中声明
当然,方法也可以在构造函数中声明
只不过,如果可以使用共用资源,我们为啥还要单独的为每一个类都声明一次呢
所以
- 在构造函数的prototype中声明,是为了实例能共享
- 在构造函数内声明,是为了属性能单独享有
理解完这个,对于理解原型链有帮助
__proto__
我们称隐性原型
prototype
我们称显性原型
看完记得点赞嘻嘻