1 前言
说起对象,应该想到的是对象的三个基本特性:封装、继承、 多态。
1.1 封装:通俗的来说,就是封装函数,通过私有化的变量和私有化的方法,不让外部访问到;
1.2 继承:简约来说可分为两种:1).通过原型prototype对象实例化实现此类的继承。2).直接实例化对象复制,完全复制父类对象;
1.3 多态: 多态就是通过对传递的参数判断来执行逻辑,即可实现一种多态处理机制。
2 继承
说起继承肯定是想起prototype , __proto__ , constructor, 那么这三者之间到底是什么一样关系呢?
下面先用一张图来展示下:
function Parent() {
// 构造函数中的this 通过new调用的,那么this指向的就是那个实例
this.name = '我是一个构造函数';
this.age = '18';
//这里定义的属性和方法都是该构造函数内的私有属性和方法
}
Parent.prototype.eat =function() { // 在原型对象定义的方法是公有的
console.log('eat');
}
console.log( Parent.prototype.constructor === Parent) // true
let parent = new Parent();parent.eat() 等价于 parent.__proto__.eat() // 先去找私有属性,找不到会去找公有属性
console.log(parent.__proto__ === Parent.prototype ) // true
实例的__proto__属性指向原型对象,调用当前实例对象的一个属性时 如果不存在,那么会沿着原型链一直寻找,直到链的末端。
链的末端: Object.prototype.__proto__
console.log( Parent.prototype.__proto__ === Object.prototype ) // true
console.log( Object.prototype.__proto__ === null ) // true
当通过new调用函数创建实例后,该实例内部包含一个指针 [[Prototype]]
指向构造函数的原型对象,该属性为内部属性,无法直接访问,但在Firfox、Chrome和Safari中有一个 __proto__
属性可以访问到构造函数的原型。
2.1 只继承私有属性
function Parent(){
this.name = 'parent';
}
Parent.prototype.eat =function() {
console.log('eat');
}
function Child(){
this.age = 9;
Parent.call(this);
}
let child = new Child();
console.log(child.name) // parent
以上定义了两个类, 一个Parent、一个Child, 在Child的内通过调用**Parent.call(this),**可以将父类的私有方法挂载在子类Child内部,这样在Child的实例上就可以拿到Parent上的方法了。
2.2 只继承公有属性
function Parent() {
this.name = 'parent';
}
Parent.prototype.eat =function() {
console.log('eat');
}
function Child() {
this.age = 9;
}
Child.prototype.smoking = function() {
console.log('吸烟');
}
Object.setPrototypeOf(Child.prototype, Parent.prototype) // 只继承公有属性
//Child.prototype = Object.create(Parent.prototype) // 只继承公有属性
let child = new Child();
child.eat() // 打印出了 eat , 拿到了父类原型对象上公有的方法了
console.log(child.name) // undefined 没有拿到父类私有属性
通过 Object.setPrototypeOf(Child.prototype, Parent.prototype) || Child.prototype = Object.create(Parent.prototype),
这两种方式, 可以实现只继承父类的私有属性。
其中Child.prototype.__proto__ = Parent.prototype; 等价于 Object.setPrototypeOf(Child.prototype, Parent.prototype),
一个是ES5中的方法, 另外一个是ES6中的方法。
Child.prototype = Object.create(Parent.prototype) 这种方法 最优
2.3 继承私有和公有属性
Child.prototype = new Parent();
// 这种方式不会使用 , 一般都是通过es6 里面的类的继承 extends 实现。
extends 可以实现私有属性、公有属性、静态方法的继承。