面向对象
多态性
- 对象的多态性
- 类型检查与多态性
- 使用继承得到多态性(继承:实现继承、接口继承)
多态最根本的作用就是通过把过程化的条件分支语句转化为对象的多态性,从而消除这些条件分支语句 - 设计模式与多态性(命令模式、组合模式、策略模式)
封装性
封装一般是对信息的隐藏(封装数据、封装实现、封装类型、封装变化),视为任何信息的隐藏;
- 封装数据
通过语法解析来实现的,由于没有public、private、protected等关键字来提供访问的权限,只能依赖变量的作用域来实现封装特性,而且只能实现public和priveta这两种特性(let、函数创建作用域、Symbol创建私有属性) - 封装实现
目的是把数据隐藏 - 封装类型
通过抽象类和接口来进行封装的 - 封装变化
23种设计模式,分为创建型模式、结构型模式、行为型模式
创建型模式:目的是封装创建对象的变化
结构型模式:封装的是组合对象之间的关系
行为型模式:封装的是行为对象的变化
保障程序的稳定性与扩展性
原型模式和基于原型继承的JavaScript对象系统
使用克隆的原型模式
原型模式是用于创建对象的一种模式;
创建对象有两种方法:1、指定类型,通过类型创建对象;2、不管类型,找到对象,克隆一模一样的对象(原型模式采用这个方法)
- Object.create() 克隆对象
var Plane = function() {
this.blood = 100;
this.attackLeval = 1;
this.defencedLeval = 1;
};
var plane = new Plane();
plane.blood = 300;
plane.attackLevel = 2;
plane.defensedLevel = 3;
var clonePlane = Object.create(plane);
console.log(clonePlane);
// Plane {}
// [[Prototype]]: Plane
// attackLevel: 2
// blood: 300
// defenseLevel: 3
- 克隆是创建对象的手段
- 原型泛型编程的一些规则
(1)所有数据都是对象;
(2)要得到一个对象,不是通过实例化类,而是找到一个对象的原型并克隆它;
(3)对象会记住它的原型;
(4)若对象无法响应某个请求时,它会把这个请求委托给自己的原型。 - javaScript中的原型继承(同样遵循原型编程规则)
(1)所有数据都是对象
基本类型(undefined、number、string、boolean、function、object)和对象类型
javascript的根对象是Object.prototype,其是一个空对象;在JavaScript中遇到的每个对象都是通过Object.prototype克隆而来。
let obj1 = new Object();
let obj2 = {};
// 通过Object.getPrototypeOf查看对象的原型
console.log(Object.getPrototypeOf(obj1) === Object.prototype); // true
console.log(Object.getPrototypeOf(obj2) === Object.prtotype); // true
(2)要得到一个对象,不是通过实例化类,而是找到一个对象并克隆它
function Person(name) {
this.name = name;
}
Person.prototype.getName = function(){
return this.name;
}
let a = new Person('Rose');
console.log(a.name); // Rose
console.log(a.getName()); // Rose
console.log(Object.getPrototypeOf(a) === Person.prototype); // true
Person不是类,而是函数函数构造器。
当new运算符调用函数的时,此时函数就是个构造器。
用new运算符创建对象的过程,实际上也只是先克隆Object.prototype对象,再进行一些其他额外的操作。
(3)对象会记住自己的原型
let a = new Object();
console.log(a.__proto__ === Object.prototype); // true
__proto__是对象与对象构造器原型联系的纽带
(4)若对象无法响应某个请求时,它会把这个请求委托给构造器的原型
let obj = {name: 'jake'};
let A = function() {};
A.prototype = obj;
let a = new A();
console.log(a.name); // jake
执行步骤:
1、遍历对象a中的所有属性,没有找到name属性;
2、查找name属性的这个请求委托对象a构造器原型,它被a.__proto__记录者并指向A.prototype,而A.prototype被设置为对象obj;
3、在对象obj中找到name属性,并返回它的值
let A = function(){};
A.prototype = {name: 'jake'};
let B = function(){};
B.prototype = new A();
let b = new B();
console.log(b.name); // jake
执行步骤:
1、遍历对象b中的所有属性,没有找到name属性;
2、查找name属性的这个请求委托对象b构造器原型,它被b.__proto__记录着并指向B.prototype,而B.prototype被设置为一个new A()创建的一个对象;
3、在该对象依旧没有找到name属性,于是请求继续委托给这个对象的构造器原型A.prototype;
4、在A.prototype中找到name属性,并返回它的值
- 原型继承的未来
es6中的class看似是类,其实质也是通过原型机制创建对象
class Animal {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
class Dog extends Animal {
constructor(name) {
super(name);
}
speak() {
return 'woof';
}
}
let b = new Dog('kkk');
console.log(b.getName(), b.speak()); // kkk, woof