JavaScript使用封装
来源:互联网 发布:狙击手模拟训练软件 编辑:程序博客网 时间:2024/06/18 13:44
基本封装方法
请看下面的例子:
var Person = function(name,age){ this.name = name; this.age = age || "未填写"; this.hobbys = ;}Person.prototype = { sayName:function{ console.log(this.name); }, sayAge:function{ console.log(this.age); }, addHobby:function(hobbys){ this.hobbys = this.hobbys.concat(hobbys); }}var person1 = new Person("Jane","20");var person2 = new Person("TabWeng","21");person1.addHobby(['sing','drawing']);person2.addHobby(['football','study','running']);person1.sayName;console.log(person1.hobbys.toString);person2.sayName;console.log(person2.hobbys.toString);
运行结果:
Jane sing,drawingTabWeng football,study,running
这在JavaScript创建对象中讲过,把可以共用的属性和方法写在原型上,需要每个实例各自都有的副本的属性和方法放在构造函数中。
现在有个问题,名称的输入不能有数字,要怎么解决呢?解决的方法可以写一个检查名称的函数,这个函数写在原型上。
var Person = function(name,age){ //校验名称 if(this.checkName(name)){ throw new Error("名字 "+name+" 不能存在数字"); } this.name = name; this.age = age || "未填写"; this.hobbys = ;}Person.prototype = { //校验函数 checkName:function(name){ re = /\d/; return re.test(name); }, sayName:function{ console.log(this.name); }, sayAge:function{ console.log(this.age); }, addHobby:function(hobbys){ this.hobbys = this.hobbys.concat(hobbys); }}var person1 = new Person("Helen666","20");var person2 = new Person("TabWeng","21");person1.addHobby(['sing','drawing']);person2.addHobby(['football','study','running']);person1.sayName;console.log(person1.hobbys.toString);person2.sayName;console.log(person2.hobbys.toString);
这段代码中,我们写了一个checkName
函数,来校验名称,暂且只是校验不能有数字吧,然后再构造函数里的第一行代码中进行校验,若校验不通过,则抛出异常。
这里我传入一个名称Helen666,结果抛出如下异常:
Error: 名字 Helen666 不能存在数字
这样就做到了一个基本的封装,实现内部校验。
但是又有个问题,我们还可以这样来定义名称:
var person1 = new Person("Helen","20");person1.name = "Helen666";person1.sayName; //Helen666
这样名称还是可以修改为不合法的名称,于是我们想到用get方法和set方法来做控制,只能通过set方法来赋值,同时通过set方法进行校验,而通过get方法来获得值。现在的代码修改如下:
// Interfacevar People = new Interface("People",["setName","getName","setAge","getAge","addHobby","getHobby","sayName","sayAge"]);var Person = function(name,age){ //implement People this.setName(name); this.setAge(age); this._hobbys = ;}Person.prototype = { //校验函数 checkName:function(name){ re = /\d/; return re.test(name); }, sayName:function{ console.log(this._name); }, sayAge:function{ console.log(this._age); }, addHobby:function(hobbys){ this._hobbys = this._hobbys.concat(hobbys); }, getHobby:function{ return this._hobbys; }, setName:function(name){ if(this.checkName(name)){ throw new Error("名字 "+name+" 不能含有数字"); } this._name = name; }, getName:function{ return this._name; }, setAge:function(age){ this._age = age || "未设置"; }, getAge:function{ return this._age; }}var person1 = new Person("Helen","20");person1.addHobby(['sing','drawing']);function record(person){ Interface.ensureImplements(person,People); person.sayName; console.log(person.getHobby.toString);}record(person1);
运行结果:
Helensing,drawing
首先,这段代码我们使用了接口,定义了People接口,而person来实现这个接口,注意注释的内容。(关于接口,请看这篇 JavaScript使用接口)
其次,我们使用了get方法和set方法来取值和赋值,我们可以约定程序员只能通过set来赋值,而在set方法里面我们对所赋予的值进行了校验,以确保准确。但是这仅仅是一种约定,程序员依然可以通过person1.name = "123"
来赋值,修改内部属性。
为了规范和起到提醒作用,我们把内部属性的命名进行规范,在这些属性前面加上“_”,比如 **_name** 、**_age** ,这样如果程序员要直接修改属性,那么他就必须这样写person1._name = "123"
,这明显是一种故意的做法,一般程序员不会这么做,起到规范和提醒的作用。
尽管如此,这种仅仅是用规定进行约束,还是无法阻止通过person1._name
进行修改,下面的方法可以做到把内部属性真正做到私有化。
通过闭包进行封装
如果对闭包不太理解,请阅读JavaScript函数表达式以及JavaScript变量和作用域,我们来看一下如何实现:
// Interfacevar People = new Interface("People",["setName","getName","setAge","getAge","addHobby","getHobby","sayName","sayAge"]);var Person = function(name,age){ //implement People // 私有变量 var _name,_age,_hobbys = ; this.addHobby = function(hobbys){ _hobbys = _hobbys.concat(hobbys); }, this.getHobby = function{ return _hobbys; }, this.setName = function(name){ if(this.checkName(name)){ throw new Error("名字 "+name+" 不能含有数字"); } _name = name; }, this.getName = function{ return _name; }, this.setAge = function(age){ _age = age || "未设置"; }, this.getAge = function{ return _age; } this.setName(name); this.setAge(age);}Person.prototype = { checkName:function(name){ re = /\d/; return re.test(name); }, sayName:function{ console.log(this.getName); }, sayAge:function{ console.log(this.getAge); }}var person1 = new Person("Helen","20");person1.addHobby(['sing','drawing']);function record(person){ Interface.ensureImplements(person,People); person.sayName; console.log(person.getHobby.toString);}record(person1);
在构造函数中,属性不使用this
,外部也就无法访问到这个属性,而闭包通过作用域链可以访问到这个属性,那么我们就通过闭包设置了为属性赋值的唯一入口,从而起到了严格校验这些属性的作用。
尽管如此,在构造函数中定义方法很多时候是没必要的,因为这样每创建一个实例,就会产生一个方法的副本,这是需要内存支持的,所以在使用的过程中,如果能用上面的基本封装方法,尽量用,除非对于私有属性有非常严格的校验要求才用闭包这种方法。
- JavaScript使用封装
- JavaScript使用封装
- 使用原生JavaScript封装cookie
- 使用JavaScript 对Cookie 操作的封装
- 使用javascript处理url的简单封装
- 原生JavaScript封装ajax,可以直接使用
- javascript系列之使用Promise封装ajax
- javascript 封装
- javascript封装
- JavaScript 封装
- JavaScript封装
- javascript 封装
- JavaScript封装
- 递归算法在javascript中使用的小技巧 (javascript的对象封装方法介绍)
- 递归算法在javascript中使用的小技巧 (javascript的对象封装方法介绍)
- 递归算法在javascript中使用的小技巧 (javascript的对象封装方法介绍)
- 递归算法在javascript中使用的小技巧 (javascript的对象封装方法介绍)
- 递归算法在javascript中使用的小技巧 (javascript的对象封装方法介绍)
- MySQL 加锁处理分析
- Chart原则: 没有万能图表,如果足够简单那么定制化是最好的
- MQTT协议笔记之mqtt.io项目TCP协议支持
- 电子小制作:手机控制的收音机
- jQuery原则
- JavaScript使用封装
- 用户行为日志-js埋点(三)浏览记录和停留时间思路
- Thinkphp3.2.3,使用方法
- 产品心经之若干
- 前端--JMingZI/ajax_jsonp(深入理解javascript跨域)
- mysql基础知识扫盲
- Confd+Etcd+endpoint+haproxy
- c# 泛型应用范例
- MQTT协议笔记之mqtt.io项目Websocket协议支持