javascript实现私有变量
来源:互联网 发布:jqueryuicore.min.js 编辑:程序博客网 时间:2024/05/16 09:32
js中对象的属性按照私有程度来说三种,第一种完全暴露型(fully exposed)只能提供公用成员,第二种方法使用下划线来表示方法或者属性的私用性。第三种是真正私用的成员,这些成员只能通过一些特权方法访问,可以通过闭包或者利用es6的语法实现
完全暴露
var Book = function(isbn, title, author){ isbn == undefined ? throw new Error('Book constructor requires an isbn'); this.isbn = isbn; this.title = title || 'No title specified'; this.author = author || 'No author specified'; } Book.prototype.display = function(){ ... }
这里的isbn如果在构造函数中没有定义,就会抛出错误,但我们也许需要对这些数据有更多的验证,那么就来到以下这种
var Book = function(isbn, title, author){ this.setIsbn(isbn); this.setTitle(title); this.setAuthor(author); } Book.prototype = { checkIsbn: function(isbn){ return isbn == undefined; }, setIsbn: function(isbn){ if(!this.checkIsbn) throw new Error('..'); this.isbn = isbn; }, setTitle: function(title){ this.title = title || 'No title specified'; }, getTitle: function(){ return this.title; }, ... } var book = new Book('a', 'book1', 'sysuzhyupeng'); book.getTitle(); // 'book1' book.title = 'book2'; book.getTitle(); // 'book2' 被改变了
尽管这样的set、get方法的设置很像一些面向对象语言如java,但没有使用private关键字导致了title、author这些属性还是公开的,这样对内部数据就无法进行保护,其他一起协作的人可能无意改动了这些属性
用命名规范区别私用成员
下划线是一种命名规范,它表明一个属性(或方法)仅供对象内部使用,直接访问它或者设置它可能导致意想不到的后果
var Book = function(isbn, title, author){ this.setIsbn(isbn); this.setTitle(title); this.setAuthor(author); } Book.prototype = { _checkIsbn: function(isbn){ return isbn == undefined; }, setIsbn: function(isbn){ if(!this._checkIsbn) throw new Error('..'); this._isbn = isbn; }, setTitle: function(title){ this._title = title || 'No title specified'; }, getTitle: function(){ return this._title; }, ... } var book = new Book('a', 'book1', 'sysuzhyupeng'); book.getTitle(); // 'book1' //然而我还是可以偷偷改变title book._title = 'book2'; book.getTitle(); // 'book2'
缺点显而易见。
使用闭包实现私有变量
在js中,只有函数具有作用域,在一些强类型语言如java中的{}就能创建块级作用域,这在js中并不存在。那么私有属性本质而言就是你希望对象外部无法访问的变量,所以实现这种需求而求助于作用域是合情合理的
var Book = function(newIsbn, newTitle, newAuthor){ //private attributes var isbn, title, author; //private method function checkIsbn(isbn){ ... } //privileged methods this.getTitle = function(){ //返回变量title,而不是this.title return title; } this.setTitle = function(newTitle){ title = newTitle || 'No title specified' } //Constructor code this.setTitle(newTitle); } //Public, non-privileged methods Book.prototype = { display: function(){ ... } } var book = new Book('a', 'book1', 'sysuzhyupeng'); book.getTitle(); // 'book1' book.title // undefined,只能通过上面的方法访问
原本我们用对象的属性,而现在使用var而不是this声明这些变量,这意味着它们只存在于Book构造器中。那么我们使用get方法取这些变量的时候,形成了闭包。 需要访问这些私有变量的方法声明在Book中即可,这些方法称为特权方法,任何不需要直接访问私有属性的方法都可以像原来那样在Book.prototype中声明。用这种对象创建方式真正实现了私有变量,但有一些缺点。完全暴露型所有方法都在原型对象中,不管new了多次,生成多少对象实例,对于方法的记录内存中只需要一份,所以这里的闭包方法性能不好。其次,这个方法也不适用于派生子类,因为js的原型继承围绕原型,可以参考我的另一篇文章原型继承和应用,一旦实现继承,子类对象根本拿不到父类中的私有变量,导致了“继承破坏封装”
通过es6实现私有变量
在es5中就已经可以通过definedProperty方法中的访问器,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
var book = { //不能是title,必须与title不同,这里使用常用命名规范,在前面加了下划线 _title: 'book1' } Object.defineProperty(book, 'title', { get: function(){ //同样不能是title,使用_title return this._title; }, set: function(value){ value == 'book2' ? this._title = value : '' } }) book.title // 'book1' book.title = 'book3'; book.title // 'book1' book.title = 'book2'; book.title // 'book2'
不方便的是这个是在创建了对象实例之后再define的,在es6中
class Book { constructor(){ this._title = 'book1'; } get title(){ return this._title; } set title(value){ value == 'book2' ? this._title = value : '' } } var book = new Book(); book.title = 'book3'; book.title // 'book1' book.title = 'book2'; book.title // 'book2'
es6中同样是构造另一个属性_title,而在读写title多了一层拦截层,然后偷梁换柱成了_title,从而实现了私有变量。如果兼容了es6,这个方法就是目前看来最好的解决方案
- javascript实现私有变量
- javascript : 用闭包实现成员变量私有的javascript bean
- Javascript 私有变量
- JavaScript私有变量
- javascript 全局变量,私有变量。
- javascript私有变量
- JavaScript学习-私有变量
- 用闭包技术实现成员变量私有的javascript bean
- 闭包实现 私有变量
- javascript实现私有属性私有方法
- JavaScript 模拟类机制及私有变量
- javascript 中公共/私有变量、方法、特权
- JavaScript闭包与私有变量
- JavaScript中私有变量的使用
- 【JavaScript学习】函数表达式:私有变量
- 实现javaScript对象属性私有
- JavaScript中定义类的公共变量和私有变量
- 私有变量
- 索引优化(一)
- 3.屏幕尺寸
- nexus 使用Nexus搭建Maven私服
- UVa227 - Puzzle
- maven安装本地jar到本地仓库
- javascript实现私有变量
- 远程debug配置
- Permission denied, please try again.
- POJ 2942 Knights of the Round Table
- C#与闭包
- 基于MVP-RxJava-Retrofit的MD风格阅读软件
- httpclient 工具类
- Python之路【第七篇】:线程、进程和协程
- win10 护眼