实例代码讲解_Person

原创文章,转载请注明\

一波三则,刚才写的都没了.

 

 

看点:面向对象  动态语言和静态语言的区别 设计模式

先看实例代码:

ContractedBlock.gif ExpandedBlockStart.gif 本人博客"关于作者"代码
 1     var Person = function(args) {
 2         
 3         this.name = "";//保护私有成员
 4         this.gender = "";
 5         this.email = "";
 6         this.msn = "";
 7         this.QQ = "";
 8         this.contact = function() {};
 9     
10         if (arguments.length != 0&&args.constructor==Object) {
11             for (var item in args) {
12                 this[item] = (this[item] != undefined ? args[item] : null);// 严格规定只有父类定义过的属性和方法才能在构造函数中直接指定值
13             }
14         }
15     };
16     var author = new Person({
17         name : 'Reany',
18         gender : "男性",
19         email : "reacigod@gmail.com",
20         msn : "reacigod@hotmail.com",
21         QQ : "51702811",
22         contact : function() {
23             alert("我最常使用的工具是gmail,所以如果你不认识我,又想联系我,最好通过gmail联系!")
24         }
25     });

没错,这就是我的博客"关于作者"页面上的代码,下面我将解析这段代码.

很明显在这段代码中定义了2个变量Person和author,这就是静态语言和动态语言的一个区别(就我有限的知识水平来说,只是js和c#的区别),静态语言基本上在是编译前已经确定好变量的类型了,而动态语言是在运行时才确定具体的变量类型.

第一 在这里Person和author都是函数型变量,一般说来,直接定义function person和function author也是完全可以的,因为,他们在大多数情况下完全可以互换.实例中使用的是"匿名方式"和后面说的是"命名方式",有时候,我们将命名方式定义函数的方法称为"声明式"函数定义,而把匿名方式定义的函数的方法称为引用是函数定义或者函数表达式(摘自"Javascript王者归来 P159").

 

首先,我们应该明确一点,Javascript是函数式编程,在Javascript中万物都是函数,可以这样理解.而现在的编程大部分是面向对象的,实际上,我们采用何种模式,目标都是一致的,就是代码的复用性,可维护性和可扩展性.在Javascript中每个函数都是Function对象的一个实例.Function一般用于动态生成的代码中使用,有具体例子再进行讲解.

第二,匿名方式和命名方式的函数定义的区别(摘自"Javascript王者归来 P159").

请看代码:

ContractedBlock.gifExpandedBlockStart.gif命名式和匿名式函数定义的区别
 1     function t1(){
 2         alert("t1");
 3     }
 4     t1();
 5     function t1(){
 6         alert("new t1");
 7     }
 8     t1();
 9     var t1=function(){
10         alert("new new t1");
11     }
12     t1(); 

如果我们执行这段函数,会惊奇的发现,并不是像我们想象的那样返回"t1,new t1,new new t1",真正的执行结果是"new t1,new t1,new new t1".这是因为声明式函数的定义的代码先于函数执行代码被解析器解析.,而引用式函数定义,或者函数表达式则是在函数运行中进行动态解析的.这个确切的说不是动态语言和静态语言的区别,而是类似于解释型语言和编译型语言的区别.本段代码中前2个t1函数就是类似于先编译,而最后一个t1类似于解释型,运行时编译,确定类型,这才是动态语言,到运行时才能真正确定类型.

第二 我们看看Person的构造.出于习惯,如果定义一个类,我们采用首字母大写的方法命名变量.

1 person的构造就很类似于其他语言.其实在Javascript中定义一个类除了这种方式外,还有一种方式就是哈希列表式.如下例:

ContractedBlock.gifExpandedBlockStart.gif哈希列表(json)式写法
1     var Person={
2         name:'',
3         gender''
4 }

就我有限的知识和匮乏的经验来说,这2种方式到底采用哪种方式好,还是自己决定好(废话+屁话).我的经验是如果这个类的属性或者方法很多,那么我们最好采用哈希方式,这样看起来很直观,在我制作的另一个框架中采用这种方式,大家如果使用过Ext,就会发现由于Ext中控件的属性或者方法很多,所以采用的这种方式.在本例中,由于只有几个属性,所以采用常用的方式,类似于author那段代码,但实际上不是那么回事,切忌他们是不同的,我只是借用这种形式,容易设置.如果有机会,我再做这2种方式的对比.

在Person中实际上做到了很好的封装.在本例中,Person没有任何对外的方法,也就是说,我们其实无法访问Person的任何东西.例如,我们无法使用"Person.name"或者"person.contact()",更直接的说Person没有用!?很奇怪吗?在这个地方采用this关键字,我们无法访问它的属性,就是私有的,而Person没有提供任何公共方法所以我们看Person就像看黑洞一样,我们什么都不知道.如果仅仅是这样,我们用c#可以完全写出类似代码,如下:

ContractedBlock.gifExpandedBlockStart.gifc#写法
1     class Person
2     {
3         private string name;
4         private string gender;
5 }

但是,明显我们在Person属性下面还有一段代码,这段代码是干什么用的呢?我们先放一放,下面让我们看author.

第三 author的奇怪问题.

我的第一个迷惑就是,author和Person的关系什么.我们按照常理会不假思索的说,他们是继承关系.想想其实也不太对,难道是Person类的实例化对象?实际上,我也不是很清楚.咋一看上去,上面2中说法都对,但是那天晚上我自己调试了很久,问题就是this的指向问题?如果是继承或者实例化,那么author也应该没有公共方法和属性,然而我们却可以使用"document.getElementById("btn").οnclick=author.contact"这句话来触发author的公共contact方法.很奇怪是吗?

实际上,一点都不能算奇怪,因为是习惯思维在误导我们.看我们的定义"var author = new Person({...})",这是一段很在其他语言中也常见的一种方式,然而现在这才是Javascript的强大之处.

其实本段并不是像其他语言那样是实例化或者简单的继承.下面都是我自己的理解,欢迎讨论.

实际上,这句话,做了2件事情.首先,"var author=new Person()".这样我们可以完全说这是一个实例化,然而如果只是这样,我们还是无法访问author的任何属性和方法啊?关键就是后面的部分.第二步就是调用Person的某个方法来让我们可以访问author的方法和属性,而这个方法就是我们在上面提到的身份不明不白的那段代码.

核心内容"this[item] = (this[item] != undefined ? args[item] : null)".

说句心里话(say a word in my heart,大家有空可以到网上搜索一下这首爆笑歌曲),我到现在也没有弄明白这里的this到底指向的是什么东西,有哪位大牛可以给我们解释一下吗.

在写这段代码的时候,我的目的就是想通过在定义author的时候直接对他进行设置.而且还要实现一个功能:假如person没有定义这个属性或者方法,那么在定义变量的时候不能直接进行其他设置.例如我使用下列代码定义:

ContractedBlock.gifExpandedBlockStart.gif这种设置将不会成功
1     var author=new Person({
2         extra:'other'
3 });

这样是非法的.例子所提供的代码是可以实现这个功能,你会发现,这样定义,我们是无法使用"author.extra"的.当初为了实现这个功能,我习惯性的思维是用callee,结果我怎么实验也不成功,而我不知怎么的,慢慢得就做出上面的样子来,结果发现成功了,功能实现了,这实在是让我喜出望外.看这个地方"this[item] != undefined",this应该是Person.然而关键是这样我们依然还是无法访问Person的任何属性和方法,但是却能访问author的属性而方法,而且author[item]==this[item],这个时候this又是author?

第三 其他零碎小知识.

1 "arguments.length != 0&&args.constructor==Object"

arguments.length主要是判断是否传递了参数,如果"var author=new Person()",那么我们是无需进行任何限制的.

args.constructor主要是判断出传递过来的参数类型是否是Object.注意typeof和constructor是不一样的.

类似的c#写法.

请大牛指点,我无法写出类似代码,即,在定义的同时进行设置.有人会说我们可以采用构造函数.但这就是静态语言和静态语言的区别.

我们只能写出下面的类似代码:

ContractedBlock.gif ExpandedBlockStart.gif c#类似的写法,但是不正确
 1     class Person
 2         {
 3             private string name;
 4             private string gender;
 5             public Person(object a) 
 6             {
 7                 this.name = a.name;
 8                 this.gender = a.gender;
 9             }
10         }

 

这是在vs2008中写出的代码,看上去,这又这样,我们才能实现上面的类似功能,然而,这是一段错误的代码.错误之处就在于其构造函数public Person(object a) 中的object,vs2008采用的.net framework 3.0/3.5借鉴了部分动态语言的优点(这点至少我是用的非常方便,项目有2.0转换为3.0/3.5之后,感觉编写的效率要高了),但是他还是编译型语言和静态语言,也就是说,他在运行前首先要编译,而在编译的时候,他不知道object到底是什么,这就需要我们先定义一个对象,这个对象存放所有的属性和方法,而其构造函数因为数目的不同,还要写相应的构造函数,这就根本不太现实,所以动态语言/解释型语言也有他自己独特的优点.

这个时候author和Person到底是什么关系.实际上,我到感觉Person是一个c#中的抽象类,而这个抽象类与c#中抽象类不同的是,他还有设置实例化对象的方法,而这个方法只有在实例化对象的时候才能是用,任何其他地方或者他自己都无法使用这个方法.

本人才疏学浅,第一次讲解代码,自己也是一知半解,所以错误在所难免,请大虾多多包涵.希望大牛不吝赐教,我等菜鸟多多交流,只有这样才能共同进步,才能促进社会主义精神文明建设,才能更快更快的实现小康社会,才能完美的构建和谐社会主义社会.


 

 

本人第一次把文章放在博客园首页,战战兢兢.我只是想让一些大牛看见,好解答我们的疑惑.

我的2个问题是:

1 文中提到的this指向的问题

2 c#中有没有类似的实现代码,就是类似于动态构造函数.不要说不实用,我们需要讨论和研究.

希望大牛们不吝赐教.

本文文档,点击下载:实例代码讲解_Person.pdf

 

转载于:https://www.cnblogs.com/Reany/archive/2008/12/05/1348063.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值