对于熟悉C#和Java的兄弟们,面向对象的三大思想(封装,继承,多态)肯定是了解的,今天我想讲讲如何在Javascript中利用封装这个特性,开讲

我们会把现实中的一些事物抽象成一个Class并且把事物的属性(名词)作为Class的Property把事物的动作(动词)作为Class的methods。在面向对象的语言中(C#等)都会有一些关键字来修饰类或者属性(Private,public,protect),这些关键词描述了访问的权限,不多做解释。

我们来看看Javascript的易变的特性(我们还用上一次的例子):

var Man = function (name, age) {
this.Name = name;
this.Age = age;
}
var Person = new Interface("Person", ["GetName", "GetAge"]);
Man.prototype = { GetName: function () { return this.Name; },
GetAge: function () { return this.Age; }
}
var Alan = new Man("Alan", 25);
alert(Alan.GetAge());
Alan.DisplayAll = function () { return "Name: "+this.GetName() + "; Age: " + this.GetAge() }
alert(Alan.DisplayAll());

我先创建了一个Class(Javascript的匿名方法)拥有2个公共的(public)的字段(本篇blog会详细讲解,继续往下看)和2个public的方法,我们创建了一个Instance--Alan,但是我可以为这个Instance动态的添加一个DisplayAll的方法,我想任何面向对象的语言是做不到这一点的,Javascript的灵活体现之一。

我们现在假设一个场景,如果有很多的程序员要用这段代码,由于Javascript的易变性,程序员就可以在实例化后改变Name的值,那初始化的动作就没有意义了:

var Alan = new Man("Alan", 25);
Alan.Name = "Alice"; //悲剧了,我alert的时候变成Alice了
alert(Alan.GetName());

所以我们不能让外部的人去任意的修改这个字段,在Java或C#中我们只需要个这个字段改为Private,就万事OK了,但是Javascript没有这个关键词,那我们需要这么做呢,这就是这篇blog存在的意义

我们可以想下在C#除了设置Private之外我们还可以怎么做?我们可以设置Setter和Getter方法。

我们来修改下上面的代码:我们称方法一:

var Person = new Interface("Person", ["SetName", "SetAge", "GetName", "GetAge"]);
var Man = function (name, age) {
this.SetAge(age);
this.SetName(name);
}
Man.prototype = {
SetName: function (name) { this.Name = name; },
SetAge: function (age) { this.Age = age; },
GetName: function () { return this.Name; },
GetAge: function () { return this.Age; }
}
var Alan = new Man("Alan", 25);
Alan.Name = "Alice"; //悲剧了,我alert的时候变成Alice了
Alan.SetAge(10);//悲剧,被别人把我的年龄给这么小
alert(Alan.GetName());
Alan.DisplayAll = function () { return "Name: "+this.GetName() + "; Age: " + this.GetAge() }
alert(Alan.DisplayAll());

我们发现貌似样子很像C#中的Setter和Getter,但是还是可以被外部修改。但是从约束上来看,貌似比上面的code要好看些,通过方法来设置初始值。但是问题还是没有解决,我们来看看下面一种方法:闭包

//我需要解释一下,在Javascript中是通过This关键字来开发权限的(Public)。

在讲闭包之前,我们需要了解下闭包的本质: 在Javascript中,只有方法是有作用域的,如果在方法中声明的变量在外部是无法访问的,那Private的概念就出来了。

var Person = new Interface("Person", ["SetName", "SetAge", "GetName", "GetAge"]);
var Man = function (newname, newage) {
var name, age;
this.SetName = function (newname) { name = newname; }
this.SetAge = function (newage) { age = newage; }
this.GetName = function () { return name; }
this.GetAge = function () { return age; }
this.SetAge(newage);
this.SetName(newname);
}
var Alan = new Man("Alan", 25);
Alan.name="Alice"; //现在name是private了,我是无法去修改的
Alan.SetAge(10); //悲剧,被别人把我的年龄给这么小
alert(Alan.GetAge());

现在私有的功能就实现了,我们只是用Var来代替了This而已。//我们把公共(Public)并且可以访问Private的方法称为特权方法,比如上面的this.SetName, this.SetAge.

如果我们的公共方法不涉及到访问Private的字段,那我们可以把他们放到Prototype中。//好处是多个实例的时候内存中也只有一分拷贝

Man.prototype.DisplayAll = function () { return "Name: " + this.GetName() + "; Age: " + this.GetAge() }

哈哈~我们来看下稍微有点难度的东西:静态变量和方法

我们都是知道静态的东西属于类(Class),我们来修改下上面的代码:

var Person = new Interface("Person", ["SetName", "SetAge", "GetName", "GetAge","GetCount"]);
var Man = (function () {
var count = 0;
return function (newname, newage) {
var name, age;
this.SetName = function (newname) { name = newname; }
this.SetAge = function (newage) { age = newage; }
this.GetName = function () { return name; }
this.GetAge = function () { return age; }
this.GetCount = function () { return count; }
this.SetAge(newage);
this.SetName(newname);
count++;
}
})();
Man.prototype.DisplayAll = function () { return "Name: " + this.GetName() + "; Age: " + this.GetAge() }
var Alan1 = new Man("Alan", 25);
var Alan2 = new Man("Alan", 25);
alert("There are "+Alan2.GetCount()+" instances of Man" );

不管我们是通过Alan1或Alan2去GetCount,结果都一样都是2. 这里count就是一个私有的静态变量。

至于为什么,不懂的可以回复我的Post,我相信大家都能看懂的~!

JavaScript设计模式之一封装的更多相关文章

  1. JavaScript设计模式-6.封装

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. 《JavaScript设计模式 张》整理

    最近在研读另外一本关于设计模式的书<JavaScript设计模式>,这本书中描述了更多的设计模式. 一.创建型设计模式 包括简单工厂.工厂方法.抽象工厂.建造者.原型和单例模式. 1)简单 ...

  3. 《JavaScript设计模式与开发实践》整理

    最近在研读一本书<JavaScript设计模式与开发实践>,进阶用的. 一.高阶函数 高阶函数是指至少满足下列条件之一的函数. 1. 函数可以作为参数被传递. 2. 函数可以作为返回值输出 ...

  4. Javascript设计模式学习一

    学习Javascript设计模式之前,需要先了解一些相关知识,面向对象的基础知识.this等重要概念,以及掌握一些函数式编程的技巧. Js多态 多态的思想:实际上是把“做什么”和“谁去做”分离开来.例 ...

  5. 常用的Javascript设计模式

    <parctical common lisp>的作者曾说,如果你需要一种模式,那一定是哪里出了问题.他所说的问题是指因为语言的天生缺陷,不得不去寻求和总结一种通用的解决方案. 不管是弱类型 ...

  6. JavaScript设计模式学习笔记

    1 JavaScript设计模式深入分析 私有属性和方法:函数有作用域,在函数内用var 关键字声明的变量在外部无法访问,私有属性和方法本质就是你希望在对象外部无法访问的变量. 特权属性和方法:创建属 ...

  7. JavaScript设计模式:读书笔记(未完)

    该篇随我读书的进度持续更新阅读书目:<JavaScript设计模式> 2016/3/30 2016/3/31 2016/4/8 2016/3/30: 模式是一种可复用的解决方案,可用于解决 ...

  8. JavaScript的学习--JavaScript设计模式的总结

    这篇博客只是自己对设计模式的理解的备忘~ 看完了<JavaScript设计模式>这本书,一直没有写博客记录一下,最近抽出时间来重读了一下,就顺便记录一下~ 如果你只是想粗略了解一下Java ...

  9. JavaScript设计模式 - 迭代器模式

    迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示. 迭代器模式可以把迭代的过程从业务逻辑中分离出来,在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺 ...

随机推荐

  1. 安卓Eclipse如何快速修改工程名及包名

    修改工程名/包名,也是我们在开发中经常遇到的问题,比如我们在开发过程中突然觉得项目名不合适,或者根包名不合适想修改一下怎么办? 如上图所示工程,我想改变一下我的项目名,如把zzz改成xxx,把我的根包 ...

  2. 饮一盏Bug留香,唱一曲项目飞扬

    沿途的风景    牵挂的项目    两情迢迢 学生档案管理项目在2月的末尾从稍带寒意的季节里完成了第一次迭代,验收的结果不尽善尽美,演示的功能也惨不忍睹,各种"关爱"的点评充斥耳旁 ...

  3. Linux内核基础

            Linux系统运行的应用程序通过系统调用来与内核通信.应用程序通常调用库函数(比如C库函数)再有库函数通过系统调用界面,让内核带其完成各种不同的任务. 下面这张图显示的就是应用程序,内 ...

  4. NoSQL数据库之Redis数据库:Redis的介绍与安装部署

     NoSQL(NoSQL = Not Only SQL),它指的是非关系型的数据库.随着互联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的w ...

  5. 安卓一键分享到qq,微信,微博,官方SDK非第三方

    当我们项目中需要集成分享功能时,我们通常会采取一下几个办法: 1.调用系统自带分享 优点:简单快速,几行代码搞定,不需添加任何额外包: 缺点:系统会调出手机内部所有带分享功能的APP,且界面风格跟随系 ...

  6. Hibernate查询,返回new对象(注意这个新定义的类要有构造函数),使用sql带条件分页查询并且把结果显示到一个对象的集里面的解决方案

     IIndexDao package com.ucap.netcheck.dao; import com.ucap.netcheck.combination.beans.IndexCombinat ...

  7. Dynamics CRM2013 ScLib::AccessCheckEx failed

    今天在系统中做某一操作的时候报如下截图错误,把错误日志下载下来,根据AccessRights这:ReadAccess一提示确定是对某一实体没有读的权限. 那怎样知道是哪个实体呢,再看上面错误日志中给出 ...

  8. 《java入门第一季》之Socket编程通信和TCP协议通信图解

    Socket编程通信图解原理: TCP协议通信图解

  9. nginx 详解反向代理负载均衡

    什么是反向代理负载均衡 使用代理服务器可以将请求转发给内部的Web服务器,使用这种加速模式显然可以提升静态网页的访问速度.因此也可以考虑使用这种技术,让代理服务器将请求 均匀转发给多台内部Web服务器 ...

  10. android eclipse写layout文件失效问题解决

    设置 xml 文件的代码提示功能 打开 Eclipse 依次选择 Window > Preferences > Xml > Editor > Content Assist &g ...