构造函数
在es6之前,对象不是基于类创建的,而是用一种称为构造函数的特殊函数来定义对象和它们的特征。
创建对象可以通过以下三种方式:
1.对象字面量
var obj1 = {}
2.new Object()
var obj1 = new Object()
3.自定义构造函数
function Student(name, age) {
this.name = name
this.age = age
this.study = function() {
console.log(this.name + '在学习')
}
}
构造函数和普通函数的不同
1、 书写方式不同,构造函数首字母习惯大写。
2、 作用不一样,构造函数用来新建实例对象。
3、 调用方式不一样,构造函数需要new 关键字来调用
4、 构造函数的函数名字和类名一样。
5、内部用this构建属性和方法, 构造函数的this指向的是对象实例本身
6、new 构造函数的执行流程
-
- 创建一个空对象
-
- 设置空对象的__proto__属性继承
构造函数constructor的prototype属性,也就是继承构造函数的原型对象上的公有属性和方法
- 设置空对象的__proto__属性继承
-
- 调用构造函数,将构造函数中的this替换为空对象的this,继承构造函数中的属性
-
- 在函数内部返回一个新对象 //简洁版的new操作符实现过程
function new(constructor) { var obj = {}; //第一步:创建一个空对象obj obj.proto = constructor.prototype; //第二步:将构造函数 constructor的原型对象赋给obj的原型 contructor.apply(obj);//第三步:将构造函数 constructor中的this指向obj,并立即执行构造函数内部的操作 return obj; // 第四步:返回这个对象 }
缺点就是浪费内存 对象实例化时,构造函数都新的内存空间。
所以一般都会 用构造函数原型对象 :prototype 所有实例对象所共享原型方法。
7、用instanceof 可以检查一个对象是否是一个类的实例,是则返回true ;所有对象都是Object对象的后代,所以任何对象和Object做instanceof都会返回true
es5继承
两个类, 实现Child 继承 Parent
function Parent() {
this.type = 'parent'
}
Parent.prototype.eat = function () {
console.log('eat')
}
function Child(name) {
this.name = name;
this.color = 'black';
}
原型继承
// 将父类指向子类的原型。
Child.prototype = new Parent();
// 所有子类共享原型,改变一个其他也会改变
构造继承
// 在子类构造函数中调用父类构造函数
function Child(name) {
Parent.call(this);
}
缺点:不能继承父类原型, 函数在构造函数中,每个子类实例不能共享函数
组合继承
使用构造函数继承父类参数, 使用原型继承父类函数
function Child(name) {
Parent.call(this);
}
Child.prototype = Parent.prototype;
缺点:父亲原型和子类原型是同一个原型, 无法区分子类是谁构造的
寄生组合继承
在组合继承的基础上,子类继承一个由父类原型生成的对象。
function Child(name) {
Parent.call(this);
}
Child.prototype = Object.create(Parent.prototype, {
constructor: {
value: Child
}
})
inherits 函数
function inherits(child, parent) {
child.super_ = parent;
child.prototype = Object.create(parent.prototype, {
constructor: {
value: child,
enumerable: false, // 否可枚举(enumerable)
writable: true, // 可写(writable)之类的
configurable: true, //当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false。
}
})
}
使用
function Child() {
Parent.call(this);
}
inherits(Child, Parent);
Child.prototype.fun = ...
es6 继承
通过class和extends可以很直观的展示Child和Parent之间的继承关系,关键要点是constructor和super两个方法的使用
constructor是每个class中都必须拥有的,如果一开始没定义会自动添加一个空的constructor方法,当使用new的时候会自动调用这个函数
super是写在子类的constructor中的方法,这个super会调用父类的构造函数,这里的这个super也是必须写的也只能写在子类的constructor中
class Parent {
// contructor
constructor(name) {
this.name = name
}
// 其他私有方法
say () {
console.log(`我的名字叫${this.name}`);
}
}
class Child extends Parent {
constructor(name, age) {
super(name);
this.age = age;
}
getAge() {
console.log(`我叫${this.name}今年${this.age}岁`);
}
}
let p = new Child("child", 18);
console.log(p);
p.say();
p.getAge();