面向对象三大特点
封装- 继承
- 多态
什么时候使用构造函数?
想重复创建多个相同结构,只是内容不同的对象时,就可以使用构造函数。
是为了实现重用对象的结构
var lilei = {
ename: "Li Lei",
age: 12,
}
var hmm = {
ename: "Han Meimei",
age: 18,
}
// 像上面的,具有相同的属性,内容不同的对象,可以使用构造函数
function Person(ename, age) {
this.ename = ename;
this.age = age;
}
var lilei = new Person("Li Lei", 12)
var hmm = new Person("Han Meimei", 18)
构造函数
封装
function Student(sname, sage) {
this.sname = sname;
this.sage = sage;
this.intr = function() {
console.info(`我叫:${this.sname}, 我${this.sage}岁`);
}
}
var lilei = new Student("Li Lei", 12);
- 为什么要使用new和this? 我们知道this指向的是调用前面的对象,比如
var obj = {
name: "ee",
intr: function() {
console.info(this.name)
}
}
obj.intr(); // 这里intr方法里面的this,指向的就是obj
那么构造函数中的this前面没有.。这个怎么解释呢?
因为new把this指定到了实例化时,新创建的空对象上了
继承
为什么出现继承?
当定义构造函数时,如果函数中有方法,每次创建实例的时候,都会重新定义function。如下面的intr方法
function Student() {
// function 等于 new Function
this.intr = function() {}
}
解决什么问题
如果将来发现多个对象都要使用相同的功能和属性时。都可以用继承来实现
什么是继承
父对象中的成员,子对象无需重复创建,就可以直接使用,就像使用自己的成员一样
如何实现继承
js中实现继承都是通过原型对象(prototype)来实现的
原型对象:替所有子对象,集中保存共有属性值和方法的父对象
如何向原型对象中添加共有属性
- 只能强行赋值
function Student(sname, sage) {
this.sname = sname;
this.sage = sage;
}
// 强行赋值
Student.prototype.intr = function() {
// 这里的this,将来谁通过 . 调用,就指谁
console.info(this.sname);
}
var lilei = new Student("Li Lei", 12);
lilei.intr();
效果如下
结果:
在子对象.访问任何成员时,js引擎先在对象内部查找自有属性。如果子对象没有,则js引擎会自动沿__proto__属性去父对象查找
多态
就是一个函数,在不同情况下表现出不同的状态
实现多态的方式:override重写。在子对象中定义同名成员,来覆盖对象中的同名成员
function Student(sname, sage) {
this.sname = sname;
this.sage = sage;
}
// 这里就实现了override,实现了多态
Student.prototype.toString = function() {
console.info("这里的toString实现了override")
}
var lilei = new Student("Li Lei", 12);
lilei.toString();
构造函数new,经过几步(4步)
构造函数是A
- 创建一个
新的空对象(Obj) - 让子对象
继承构造函数的原型对象
Obj.__proto__ = A.prototype
- 调用构造函数,将构造函数中的
this指向Obj;在构造函数内部通过强行赋值的方法,为新对象Obj添加属性和方法
// 构造函数中的this.sname = sname。就相当于Obj.sname = sname;
- 返回新对象的地址
关键词
- prototype:原型对象,也叫父对象,用于实现继承。是在定义构造函数的时候使用
- proto:实例的原型,prototype定义的方法属性,实例是通过这个来查找的。
两个指向一个地址