构造函数的“前世今生”——拒绝“八股文”

为什么会出现构造函数

假设我们要统计学校老师的姓名、性别、年龄、科目,可以用对象来表示

const teacher1 = { name: '李雷', gender: 'man', age: 30, subject: 'maths' };
const teacher2 = { name: '韩梅梅', gender: 'woman', age: 20, subject: 'Chinese' };
const teacher3 = { name: 'Peter', gender: 'man', age: 40, subject: 'English' }; 

虽然可以清楚地记录老师的信息,但是写了很多的重复代码(name、gender、age、subject),构造函数的出现就是为了帮助我们解决此类问题我们先来了解一下构造函数的定义,再来创建一个构造函数去解决这类问题

什么是构造函数

讨论构造函数与普通函数的区别,其实就是讨论构造函数的定义

  • 构造函数是使用new关键字调用的函数
  • 声明构造函数时,一般首字母大写
function Teacher() {}// 空的构造函数Teacher 

首字母大写并不强制,是程序猿间约定俗成的“浪漫”,非要做一个“直男/女”也是可以的

创建一个构造函数

我们来创建一个构造函数,用来统计上面的老师信息

// 声明构造函数Teacher
function Teacher(name, gender, age, subject) {this.name = name;this.gender = gender;this.age = age;this.subject = subject;
}

// 创建3个teacher对象
const teacher1 = new Teacher('李雷', 'man', 30, 'maths');
const teacher2 = new Teacher('韩梅梅', 'woman', 20, 'Chinese');
const teacher3 = new Teacher('Peter', 'man', 40, 'English'); 

我们成功省略了重复代码,并清晰地表达出3个老师的信息

new操作符的作用

上面说到除了首字母大写,构造函数和普通函数的区别就是使用new进行调用,那么new关键字帮助我们做了什么?

const teacher = new Teacher(); 

当我们创建teacher对象时,new帮我们做了下面4件事

// 步骤1:创建空对象
const obj = new Object();
// 步骤2:使空对象的隐式原型指向构造函数的显示原型
obj.__photo__ = Teacher.prototype;
// 步骤3:使指针this指向空对象
Teacher.call(obj); 

步骤4有些特殊,有2种情况

// 步骤4:返回值给teacher对象
// 情况1:当构造函数有返回值,且返回值为对象类型,直接返回该对象
function Teacher(name, age) {this.name = name;this.age = age;return {hobby: '打篮球'}
}
const teacher1 = new Teacher('张三', 19);
console.log(teacher1); // { hobby: '打篮球' }

// 情况2:除情况1外的其他情况,返回this对象
function Student(name, age) {this.name = name;this.age = age;
}
const student1 = new Student('李四', 36);
console.log(student1); // { name: '李四', age: 36 } 

实例对象的属性和方法

实例对象的属性和方法,可以通过2种方式获得:(1)构造函数内定义的属性和方法,每个实例对象相互独立,不能共享(2)实例对象继承原型对象中的属性和方法,可以共享

构造函数定义

构造函数内定义的属性和方法,每个实例对象相互独立,不能共享

function Teacher(name, age) {this.name = name;this.age = age;this.say = function() {console.log(`I am ${this.name}`);}
}

const teacher1 = new Teacher('李雷', 35);
const teacher2 = new Teacher('韩梅梅', 40);

console.log(teacher1.name); // 李雷
console.log(teacher2.name); // 韩梅梅
console.log(teacher1.age); // 35
console.log(teacher2.age); // 40
teacher1.say(); // I am 李雷
teacher2.say(); // I am 韩梅梅 

继承

实例对象继承原型对象中的属性和方法,可以共享

function Teacher(name) {this.name = name;this.age = age;
}
Teacher.prototype.profession = '老师';
Teacher.prototype.say = function () {console.log(`I am ${this.name}`);
}

const teacher1 = new Teacher('李雷', 35);
const teacher2 = new Teacher('韩梅梅', 40);

console.log(teacher1.name); // 李雷
console.log(teacher2.name); // 韩梅梅
console.log(teacher1.age); // 35
console.log(teacher2.age); // 40
console.log(teacher1.profession); // 老师
console.log(teacher2.profession); // 老师
teacher1.say(); // I am 李雷
teacher2.say(); // I am 韩梅梅 

我们将say方法从构造函数放到了原型对象中,并新增了一个属性profession,他们都可以被实例对象继承并使用

为什么要将部分属性和方法声明在原型对象上> (1)节省内存空间(每个对象都需要浏览器引擎单独分配内存,我们将对象中的公用属性和方法放到原型中,只需分配一次内存)> (2)符合面向对象的思想(我们将“老师”抽象为teacher对象,name、age是每个老师独有的特征,gender、say是所有老师公有的特征)

最后

最近找到一个VUE的文档,它将VUE的各个知识点进行了总结,整理成了《Vue 开发必须知道的36个技巧》。内容比较详实,对各个知识点的讲解也十分到位。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值