JavaScript面向对象编程之封装(数据、实现、类型、变化)
封装数据
静态类型语言的对象系统中,封装数据是由语法解析来实现的,比如:private、public、protected 等关键字来提供不同的访问权限。
Javascript 并没有提供对这些关键字的支持,我们只能依赖变量的作用域来实现封装特性,而且只能模拟出 public 和 private 这两种封装特性。
除了 es6 中提供的 let const 之外,一般我们可以通过函数来创建作用域:
// 闭包
var myObject = (function() {
var __name = 'sven'; // 私有(private)变量
return {
getName: function() { // 公开(public)方法
return __name;
}
}
})();
console.log(myObject.getName()); // sven
console.log(myObject.__name); // undefined
在 es6 中,还可以通过 Symbol 创建私有属性。
var MyClass = (function() {
// module scoped symbol
var key = Symbol("key");
function MyClass(privateData) {
this[key] = privateData;
}
MyClass.prototype = {
doStuff: function() {
... this[key] ...
}
};
return MyClass;
})();
var c = new MyClass("hello")
c["key"] === undefined
参阅:https://github.com/lukehoban/es6features
封装实现
从封装实现细节来讲,封装使得对象内部的变化对其他对象而言是透明的,不可见的。对象对它自己的行为负责。其他对象都不关心它的内部实现。封装使得对象之间的耦合变松散,对象之间只通过暴露接口来通信。当我们修改一个对象时,可以随意地修改它的内部实现,只要对外的接口没有变化,就不会影响到程序的其他功能。比如:编写 each 函数,它的作用是遍历一个聚合对象,使用这个 each 函数的人不用关心它的内部是怎么实现的,只要它提供的功能正确就可以。
封装类型
封装类型在静态语言中一种重要的封装方式。一般而言,封装类型是通过抽象类和接口来进行的。
Javascript 中,并没有对抽象类和接口的支持。其本身也是一门类型模糊的语言,在封装类型方面,Javascript 没有能力,也没有必要做更多。对于 Javascript 的设计模式实现来说,不区分类型是一种失色,也可以是一种解脱。
封装变化
“找到变化并封装之”,通过封装变化的方式,把系统中不变的部分和容易变化的部分隔离开来,在系统中演变过程中,我们只需要替换那些容易变化的部分,如果这些部分是已经封装好的,替换起来也相对简单。