构造函数
声明
普通方法的声明方式
//声明构造函数
function Person(name,age){
this.name = name;
this.age = age
}
//实例化两个构造函数
const obj = new Person("小王",20);
const obj2 = new Person("小李",22);
规范
- 声明构造函数时需要首字母大写 用以区分普通方法
- new 的时候如果不传递参数可以省略小括号,例如:const obj = new Person;(不推荐这种写法!!!)
规则
- 实例的时候必须要和new连用
- 实例时不和new连用就是一个普通方法,没有创建对象的能力
- 构造函数中不要写return
- 如果return基本数据类型,则没有任何意义;
- 如果return复杂数据类型,构造函数将不能正确的创建对象;
意义
就是为了创建一个有属性和方法的合理的对象
多次创建函数问题
在构造函数中写方法的时候,会根据创建的对象的多少重复创建这个函数,会造成资源浪费
//问题如下:
//声明构造函数
function Person(name){
this.name = name;
this.fn = function(){
}
}
//实例化构造函数
const obj = new Person("小林");
const obj2 = new Person("小赵");
console.log(obj.fn===obj2.fn);//打印结果为:=false
结论证明直接在构造函数中写方法的话,我们在实例的时候,
每次例化的对象中的方法的指向地址都不一样,这样会造成资源浪费
解决问题
先来了解一下“prototype”和“proto”两个属性
“prototype”
- 每一个函数(包括普通函数和构造函数)天生自带一个prototype属性,这是一个对象空间
- 我们可以通过这个属性向函数中添加一些内容
“__proto__”
- 每一个对象都天生带一个属性"__proto__",指向所属构造函数的prototype空间
//声明构造函数
function School(personNum){
this.personNum = personNum;
}
//给函数空间增加一个方法体
School.prototype.searchBoyNum=function(){
console.log("查找有多少男同学");
}
//实例化构造函数
const obj = new School(1000);
console.log(obj);
console.log(obj.__proto__===School.prototype);
打印结果如下:
证明:在构造函数中构造函数的prototype与实例化对象的__proto__指向的地址是一样的,
构造函数用prototype的方式向构造函数中添加方法信息在实例化的对象中一样可以使用。
//声明构造函数
function School(personNum){
this.personNum = personNum;
}
//给函数空间增加一个方法体
School.prototype.searchBoyNum=function(){
console.log("查找有多少男同学");
}
//实例化构造函数
const obj = new School(1000);
const obj2 = new School(500);
let fn1=obj.searchBoyNum();
let fn2 =obj2.searchBoyNum();
console.log(fn1===fn2);//打印结果为:true
结论:通过打印结果,我们知道,通过这种方式,多次实例的构造函数中的方法指向相同的地址,
这种方式规避了资源浪费
总结
- 当你需要向构造函数中添加属性的时候,就写在构造函数里面
- 当你需要向构造函数中添加方法的时候,写在构造函数的prototype空间里面
this指向
构造函数中的this指向当前实例
构造函数中的prototype上的方法里面的this也指向当前实例