javascrpit面向对象之综合
 
  这一章是对前几章的一个总结,通过一个案例来综合认识javascript面向对象的基本用法
 
需求:
  几乎所有的web应用都需要保存数据一些到本地,那么我们就来做一个数据储存器吧。
详细需求需求:
  当本地储存有数据时,取用本地的数据,没有时使用默认的数据
  判断本地的数据是否过时,如果过时则不使用
  默认使用localStorage,但支持使用其它储存方式,并且要支持多方储存,多方读取
抽象出对象
根据需求里面的关键字,我们抽象出三个对象:数据访问、数据、储存器
  数据储存管理器负责管理数据,对外暴露接口
  数据对象负责对数据的操作
  储存器负责保持数据,读取数据
储存器对象
  DataStorageManagerBase暴露两个接口save()和load(),模拟抽象类,告诉子类一定要实现这两个方法。
  下面的例子用LocalStorage实现了一个子类,当然你也可以用cookie或其它方式实现。
  为什么要把LocalStorage这些储存器进行二次封装呢?直接用不就可以了吗?
  因为各种储存器等api都是不一样等,我们二次封装后可以确保无论什么储存器对外暴露的接口都是save()和load()。
/*模拟数据储存器抽象类,其实这个类不要也可以*/
class DataStorageManagerBase {
static getIns() {
/* 储存器在整个应用的生命周期里应该只有一个实例 */
if (!this._ins) this._ins = new this();
return this._ins;
}
constructor() {
this.name = null;
}
save(name/* string */, data/* any */) {
throw '"' + this.constructor.name + "'类没有save()方法";
}
load(name/* string */) {
throw '"' + this.constructor.name + "'类没有load()方法";
}
}
class LocalStorageManager extends DataStorageManagerBase {
static getIns() {
/* 静态方法不能继承 */
if (!this._ins) this._ins = new this();
return this._ins;
}
constructor() {
super();
this.name = 'localStorage';
}
save(name/* string */, data/* any */) {
console.log(name,data)
if (!window.localStorage) return this;//判断这个储存器可用不可用,你也可以在这里抛出错误
window.localStorage[name] = JSON.stringify(data);
return this;
}
load(name/* string */) {
//如果储存器不可用,返回false
if (!window.localStorage) return false;
//如果没有这个数据,返回false
if (!window.localStorage[name]) return false;
let dataLoaded = JSON.parse(window.localStorage[name]);
return dataLoaded;
}
}
数据对象
  对数据的操作:保存、读取、判断版本等
class GlobalData {
static addStorage(storage/* DataStorageManagerBase */) {
/*动态添加储存器*/
this._storages.push();
}
static getStorages() {
return this._storages;
}
constructor(name, data, version) {
this.name = name;
this.data = data;
this.version = version || 1;
this._loadData();
//初始化的该对象的时候,读取localStorage里的数据,看有没有已储存的数据,有就用该数据
}
getData() {
return this._copy(this.data);
}
setData(data, notSave) {
this.data = this._copy(data);
if (!!notSave) return this;
let dataToSave = {
name: this.name,
version: this.version,
data: this.data
};
let storages = GlobalData.getStorages();
for (let i = 0, l = storages.length; i < l; i++) {
/*轮询所有储存器,把数据保存在这些储存器中*/
storages[i].save(this.name,dataToSave);
}
return this;
}
_copy(data) {
/*深拷贝*/
if (typeof data != "object") return data;
return JSON.parse(JSON.stringify(data));
}
_loadData() {
let storages = GlobalData.getStorages();
for (let i = 0, l = storages.length; i < l; i++) {
/*轮询所有储存器,依次获取数据*/
const dataLoaded = storages[i].load(this.name);
if(!!dataLoaded) {
this._updateData(dataLoaded);
return;
}
}
}
_updateData(dataLoaded) {
if (dataLoaded.version < this.version) return this;
this.data = dataLoaded.data;
return this;
}
}
GlobalData._storages = [LocalStorageManager.getIns()];// 默认添加LocalStorageManager储存器
数据访问对象
对数据对象管理,对外暴露三个接口getData(),setData(),config(),用户通过这三个接口使用这个模块
class GlobalDataDao {
static getIns() {
if (!this._ins) this._ins = new this();
return this._ins;
}
constructor() {
this.GlobalDataClass = GlobalData;
this._dataList = [];
}
getData(name/* string */) {
let dataIns = this.getDataIns(name);
if (!!dataIns) {
return dataIns.getData();
} else {
return null;
}
}
setData(name/* string */, data/* any */, notSave = false/* ?boolean */) {
let dataIns = this.getDataIns(name);
dataIns.setData(data, notSave);
return this;
}
config(configs/* Array<Config> */) {
/* 初始化数据
interface Config {
name: string;
data; any;
version?: number;
}
*/
for (let i in configs) {
let de = configs[i];
if (!!this.getDataIns(de.name)) {
/* 如果数据名重复,抛出错误 */
throw new Error('data name "' + de.name + '" is exist');
};
let dataIns = new GlobalData(de.name, de.data, de.version);
this._dataList.push(dataIns);
}
return this;
}
getDataIns(name/* string */) {
for (let i in this._dataList) {
if (this._dataList[i].name === name) {
return this._dataList[i];
}
}
return false;
}
}

使用

/*用法*/
let globalDataManeger = GlobalDataDao.getIns(); let configs = [
{
name: 'languageUsing',
version: 1,
data: {
name: '简体中文',
value: 'zh-cn'
}
}, {
name: 'userPreference',
version: 1,
data: {
theme: 'blue',
menu: 'side_bar'
}
}
];
globalDataManeger.config(configs);
console.log(globalDataManeger);
let languageUsing = globalDataManeger.getData('languageUsing');
console.log(languageUsing);
languageUsing.name = 'English';
languageUsing.value = 'en';
globalDataManeger.setData('languageUsing', languageUsing);

JavaScript面向对象轻松入门之综合的更多相关文章

  1. JavaScript面向对象轻松入门之封装(demo by ES5、ES6、TypeScript)

    本章默认大家已经看过作者的前一篇文章 <JavaScript面向对象轻松入门之抽象> 为什么要封装? 封装(Encapsulation)就是把对象的内部属性和方法隐藏起来,外部代码访问该对 ...

  2. JavaScript面向对象轻松入门之概述(demo by ES5、ES6、TypeScript)

    写在前面的话 这是一个JavaScript面向对象系列的文章,本篇文章主要讲概述,介绍面向对象,后面计划还会有5篇文章,讲抽象.封装.继承.多态,最后再来一个综合. 说实话,写JavaScript面向 ...

  3. JavaScript面向对象轻松入门之多态(demo by ES5、ES6、TypeScript)

    多态(Polymorphism)按字面的意思就是"多种状态",同样的行为(方法)在不同对象上有不同的状态. 在OOP中很多地方都要用到多态的特性,比如同样是点击鼠标右键,点击快捷方 ...

  4. JavaScript面向对象轻松入门之抽象(demo by ES5、ES6、TypeScript)

    抽象的概念 狭义的抽象,也就是代码里的抽象,就是把一些相关联的业务逻辑分离成属性和方法(行为),这些属性和方法就可以构成一个对象. 这种抽象是为了把难以理解的代码归纳成与现实世界关联的概念,比如小狗这 ...

  5. JavaScript面向对象轻松入门之继承(demo by ES5、ES6)

    继承是面向对象很重要的一个概念,分为接口继承和实现继承,接口继承即为继承某个对象的方法,实现继承即为继承某个对象的属性.JavvaScript通过原型链来实现接口继承.call()或apply()来实 ...

  6. JavaScript面向对象编程入门

    来源极客网 function Person() { var _this = {} //创建一个空的对象,接着我们利用这个"空的对象"承载Person的属性和方法 _this.say ...

  7. 风趣的JavaScript面向对象入门课程一

    在我们程序猿界一直流传这这么一个joke,没女票我们可以new一个.没房子没票子没车子我们同样new一个!当然这听着更像是一种自嘲,毕竟我们程序猿都爱自嘲,哈哈,废话不多说,今天就由我带着你们来入Ja ...

  8. 《javascript面向对象精要》读书笔记

    <javascript面向对象精要> 买这本书的原因主要是因为作者,Nicholas C. Zakas 牛X闪闪的js专家,读过js高程的应该都知道他,而这本书是他的最新力作,感觉也是js ...

  9. 快速学习JavaScript面向对象编程

    到处都是属性.方法,代码极其难懂,天哪,我的程序员,你究竟在做什么?仔细看看这篇指南,让我们一起写出优雅的面向对象的JavaScript代码吧! 作为一个开发者,能否写出优雅的代码对于你的职业生涯至关 ...

随机推荐

  1. webstorm bable

    一.设置npm源 1.得到原本的镜像地址 npm get registry > https://registry.npmjs.org/ 设成淘宝的 npm config set registry ...

  2. c++中vector向量几种情况的总结(向量指针,指针的向量)

    1.标准库vector类型 vector 是同一种类型的对象的集合.每一个对象都有一个相应的整数索引值.标准库将负责管理与存储元素相关的内存.我们把 vector 称为容器,是由于它能够包括其它对象. ...

  3. VBscript 做的设置网卡名称

    Set WSHShell=WScript.CreateObject("WScript.Shell") Dim NetcardDescriptionDim NetcardName i ...

  4. 运营或生态链没做好,APP质量再高有个鸟用(下)

    上篇文章已经阐述了对于一款产品卖不卖作,事实上非常依赖于运营的打造和生态链的建立,这里能够解释为什么很多优秀的游戏产品功底非常好,但開始并不卖作,仅仅有碰到一家肯出力推的渠道游戏才迅速火了起来.这是不 ...

  5. Linux 用户和文件权限管理

    Linux —— 用户权限管理 权限: 为什么需要权限管理?    1.计算机资源有限,我们需要合理的分配计算机资源.    2.Linux是一个多用户系统,对于每一个用户来说,个人隐私的保护是十分重 ...

  6. iGrimaceVX3.0和1.44在线源手机直接安装教程

    [第一步] 先安装好三个组件设备必须是苹果越狱好后 确定6点几跟7点几的版本号才干够 首先打开cydia 选开发人员 以下 点软件源 点右上角编辑  1加入源 apt.25pp.com和IG包下载源a ...

  7. Redis 脚本及其应用

    参考:http://www.runoob.com/redis/redis-scripting.html Redis 脚本使用 Lua 解释器来执行脚本. Reids 2.6 版本通过内嵌支持 Lua ...

  8. 多媒体开发之---h264 取流解码分析

    1. nalu_unit_type = *((unsigned char *)pEmptyBuf->bufVirtAddr+4); nalu_unit_type = nalu_unit_type ...

  9. STL--map用法

    STL--map用法map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力由于这个特性它完成有可能在我们处理 ...

  10. NBUT 1222 English Game(trie树+DP)

    [1222] English Game 时间限制: 1000 ms 内存限制: 131072 K 问题描写叙述 This English game is a simple English words ...