javascript设计模式 封装和信息隐藏(上)_javascript技巧
本文分上下两部分,上部讲基本模式(basic patterns):完全暴露法,下划线标记法和使用闭包;下部讲高级模式(Advanced Patterns),如何实现静态方法和属性,常量还有其他一些知识点。
封装是面向对象语言很基本也是很有用的特性,虽然javascript也可以称的上是面向对象语言,但他对封装的支持并不是很好,不像其他语言,只要使用private、protected就可以实现。但这并不是说就没有办法了,下面我就介绍下如何在javascript中实现封装。
一、基本模式(basic patterns),主要包括三种方式:完全暴露法,下划线标记法和使用闭包。(闭包是个很重要,也是很难的概念,有兴趣的朋友可以去网上找资料,我博客里也转载了别人的文章)。
这里我们以book类作为例子,需要创建和初始化book类。
// Book(isbn, title, author)
var theHobbit = new Book('0-395-07122-4', 'The Hobbit', 'J. R. R. Tolkien');
theHobbit.display(); // Outputs the data by creating and populating an HTML element.
1.完全暴露法:
创建book类可以用最传统的构造函数方式,
var Book = function(isbn, title, author) {
if(!this.checkIsbn(isbn)) throw new Error('Book: Invalid ISBN.');
this.isbn = isbn;
//代码中 || 的作用是 如果title无值,则会把'No title specified'赋给 this.title。这种方式很好用,大家可以在自己的代码中使用。
this.title = title || 'No title specified';
this.author = author || 'No author specified';
}
Book.prototype = {
//验证isbn函数
checkIsbn: function(isbn) {
...
},
//获取isbn
getIsbn: function() {
return this.isbn;
},
//设置isbn
setIsbn: function(isbn) {
if(!this.checkIsbn(isbn)) throw new Error('Book: Invalid ISBN.');
this.isbn = isbn;
},
//获取title
getTitle: function() {
return this.title;
},
//设置title
setTitle: function(title) {
this.title = title || 'No title specified';
},
//获取作者
getAuthor: function() {
return this.author;
},
//设置作者
setAuthor: function(author) {
this.author = author || 'No author specified';
},
//显示函数
display: function() {
...
}
};
代码有点多,我在这里简单讲解下。javascript中创建类和c#,java有点不同,c#,java会把所有方法和属性包在一个类文件里面,比如说
public class book()
{
private string isbn;
public string ISBN
{
set
{
this.isbn=value;
}
get
{
return this.isbn;
}
}
...
private bool CheckIsbn(string isdn)
{
......
}
......
public void Display()
{
......
}
}
javascript也可以用这种方式,但是推荐使用我上面使用的把属性定义到类定义函数(或者叫构造函数),方法定义到prototype对象中,这种做法性能要好些,至于原因大家可以去google。
上面的js代码想实现的功能是,定义一个book类,类里面包括三个私有变量(或者叫属性)isbn,title,author,一个私有方法checkIsbn,几个公有方法getIsdn,setIsdn,...display。想法是好的,但是现实是残酷的,其实那些私有属性或者方法根本一点都不私有。比如说,theHobbit.isbn = '978-0261103283';你可以用这种方式为isbn赋值,不会报错而且绝对成功。原因就是javascript没有private方式去实现对特定对象的私有化。此外这种实现方式在使用时也会造成困惑,到底类的创建者想暴露哪些属性和方法呢?下面介绍第一种改进办法,下划线标记法。
2.下划线标记法:
var Book = function(isbn, title, author) {
// Constructor code.
this.setIsbn(isbn);
this.setTitle(title);
this.setAuthor(author);
}
Book.prototype = {
//验证isbn函数
_checkIsbn: function(isbn) {
...
},
//获取isbn
getIsbn: function() {
return this._isbn;
},
//设置isbn
setIsbn: function(isbn) {
if(!this._checkIsbn(isbn)) throw new Error('Book: Invalid ISBN.');
this._isbn = isbn;
},
...
//显示函数
display: function() {
...
}
};
其实就是在所有想实现私有的属性或者方法前面加了下划线_,没别的操作。这种方法并没有实现真正的私有化,theHobbit._isbn = '978-0261103283';这样操作照样成功,这种方式最大的意义在于告诉类的使用者,作者本意上想暴露哪些对象,不想暴露哪些。但是使用者是否按照作者的想法去做,作者是控制不了的。
那有没有办法实现真正的私有化呢,答案是有的,就是利用闭包。
3.使用闭包:
javascript之所以能实现真正的封装,是和他特有的函数作用域,函数支持内部函数,还有闭包分不开的。大家可以去网上搜集相关知识加深理解。
下面首先说的就是函数作用域,在javascript中如果在一个函数内部定义了一个变量,那么函数外部是没有办法访问的。其实在javascript中实现私有属性或者方法就是利用了它这一特殊属性。例子:
function foo() {
var a = 10;
function bar() {
a *= 2;
}
bar();
return a;
}
在上面的例子中函数foo在内部定义了变量a和方法bar,在foo外部是无法访问到a和bar的,但是因为a和bar都定义在foo内部,但bar是可以访问到a的。那么有没有办法能在foo外部访问到bar呢,答案是有的,就是使用闭包。
function foo() {
var a = 10;
function bar() {
a *= 2;
return a;
}
return bar;
}
var baz = foo(); // baz is now a reference to function bar.
baz(); // returns 20.
baz(); // returns 40.
baz(); // returns 80.
var blat = foo(); // blat is another reference to bar.
blat(); // returns 20, because a new copy of a is being used.
这就是在前面提到的javascript函数支持内部函数。内部函数bar可以访问私有变量a,函数foo又把内部函数bar抛出给baz,baz就可以访问到内部变量a了,这就实现了闭包。大家一看也就明白了,这样其实就实现了私有变量和方法。回到我们前面的book例子,实现如下:
var Book = function(newIsbn, newTitle, newAuthor) {
// implements Publication
// Private attributes.
var isbn, title, author;
// Private method.
function checkIsbn(isbn) {
...
}
// Privileged methods.
this.getIsbn = function() {
return isbn;
};
this.setIsbn = function(newIsbn) {
if(!checkIsbn(newIsbn)) throw new Error('Book: Invalid ISBN.');
isbn = newIsbn;
};
this.getTitle = function() {
return title;
};
this.setTitle = function(newTitle) {
title = newTitle || 'No title specified';
};
this.getAuthor = function() {
return author;
};
this.setAuthor = function(newAuthor) {
author = newAuthor || 'No author specified';
};
// Constructor code.
this.setIsbn(newIsbn);
this.setTitle(newTitle);
this.setAuthor(newAuthor);
};
// Public, non-privileged methods.
Book.prototype = {
display: function() {
...
}
};
上述代码就实现了 isbn, title, author和checkIsbn的私有化,外部是决定不能直接访问到的。如需访问 isbn, title, author只能通过对象级的方法getTitle,setTitle...。比如要给isbn赋值,只能用theHobbit.setIsbn = '978-0261103283';,如果你还用theHobbit._isbn = '978-0261103283';,对不起要报错了。
好了,今天的内容就讲到这里了,希望对大家有帮助。
作者:下一站永远

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

本站4月17日消息,集邦咨询(TrendForce)近日发布报告,认为英伟达Blackwell新平台产品需求看涨,预估带动台积电2024年CoWoS封装总产能提升逾150%。英伟达Blackwell新平台产品包括B系列的GPU,以及整合英伟达自家GraceArmCPU的GB200加速卡等。集邦咨询确认为供应链当前非常看好GB200,预估2025年出货量有望超过百万片,在英伟达高端GPU中的占比达到40-50%。在英伟达计划下半年交付GB200以及B100等产品,但上游晶圆封装方面须进一步采用更复

本站7月9日消息,AMDZen5架构“Strix”系列处理器会有两种封装方案,其中较小的StrixPoint将采用FP8封装,而StrixHalo将会采用FP11封装。图源:videocardz消息源@Olrak29_最新曝料称StrixHalo的FP11封装尺寸为37.5mm*45mm(1687平方毫米),和英特尔AlderLake、RaptorLakeCPU的LGA-1700封装尺寸相同。AMD最新的PhoenixAPU采用FP8封装方案,尺寸为25*40mm,这意味着StrixHalo的F

通过封装代码,C++函数可以提高GUI开发效率:代码封装:函数将代码分组到独立单元,使代码易于理解和维护。可重用性:函数可创建通用功能供应用程序中重复使用,减少重复编写和错误。简洁代码:封装代码使主逻辑简洁,便于阅读和调试。

PHP中的封装技术及应用封装是面向对象编程中的一个重要概念,它指的是将数据和对数据的操作封装在一起,以便提供对外部程序的统一访问接口。在PHP中,封装可以通过访问控制修饰符和类的定义来实现。本文将介绍PHP中的封装技术及其应用场景,并提供一些具体的代码示例。一、封装的访问控制修饰符在PHP中,封装主要通过访问控制修饰符来实现。PHP提供了三个访问控制修饰符,

Vue中Axios封装及其常用方法介绍Axios是一款基于Promise实现的HTTP库,它的优点在于具有良好的可读性、易用性以及可扩展性。Vue作为一款流行的前端框架,也对Axios提供了全面支持。本文将介绍如何在Vue中进行Axios封装,并且介绍Axios常用的一些方法。一、Axios封装在开发过程中,我们常常需要对Axios进行一些自定义的封装,例如

本站7月11日消息,经济日报今天(7月11日)报道,富士康集团已进军先进封装领域,重点布局时下主流的面板级扇出封装(FOPLP)半导体方案。1.继旗下群创光电(Innolux)之后,富士康集团投资的夏普(Sharp)也宣布进军日本面板级扇出式封装领域,预计将于2026年投产。富士康集团在AI领域本身就有足够的影响力,而补上先进封装短板之后让其可以提供“一条龙”服务,便于后续接受更多的AI产品订单。本站查询公开资料,富士康集团目前持有夏普10.5%的股权,该集团表示现阶段不会增持,也不会减持,将维

Python作为一门高级编程语言,被广泛应用于数据分析、机器学习、Web开发等领域。然而,随着代码规模不断扩大,Python程序的可扩展性问题也逐渐显现出来。可扩展性差错误是指Python程序在某些情况下不能很好地适应需求变化,无法对大规模数据进行处理,导致程序运行效果不佳。太多的依赖、糟糕的代码结构、缺乏文档等都是Python程序可扩展性差错误的罪魁祸首。

如何在Go语言中实现封装和继承封装和继承是面向对象编程中的两个重要概念,它们可以使代码更加模块化和可维护,同时也为代码的复用提供了便利。本文将介绍在Go语言中如何实现封装和继承,并提供相应的代码示例。封装封装是将数据和功能进行封装,隐藏实现的细节,只暴露必要的接口给外部使用。在Go语言中,封装是通过导出和非导出标识符来实现的。首字母大写的标识符可以被其他包访
