没有眼泪
Don't Cry!
posts - 7,comments - 5,trackbacks - 0
        终于到了要离开的一天,毕业之后来到这家公司,从一个毕业生成长为一个程序员,经历过许多辛酸与磨炼,回想往事,眼前浮现出曾经那一张张熟悉的面孔.谢谢曾经给过我帮助的同事与朋友,没有你们也没有今天的我,希望大家越来越好,也希望公司越来越好,也希望自己能有个美好的未来.
posted @ 2008-05-09 17:12 zhangchao 阅读(56) | 评论 (0)编辑 收藏
        众所周知,javascript中的继承是通过原型对象(prototype)来实现的.原型对象是由函数的构造函数创建,它所拥有的属性能被所有对象共享.初始时原型对象指向一个Object对象,并且定义了一个constructor属性,该属性指向定义该原型对象的构造函数本身,上述过程可以理解为以下代码:
function BaseClass() {
    document.write('This is BaseClass.');
}
BaseClass.prototype 
= new Object();
BaseClass.prototype.constructor 
= BaseClass;
因为原型对象的所有属性能被构造函数创建对象共享,所以创建的对象可以访问这里的constructor属性:
var c = new BaseClass();
document.write(c.constructor 
== BaseClass); //true
c.constructor(); //调用BaseClass函数,输出This is BaseClass.
由于对象本身也可以自定义属性,所以在读取对象属性时js先检查该对象是否定义了该属性,如果已经定义了则使用该属性,如果没有定义则再从其原型对象中读取该属性,所以如果对象自定义的属性和其原型中的属性存在重名则自定义属性"隐藏"了其原型对象中的同名属性.例:
c.constructor = function() {
    document.write('This is c');
}
c.constructor(); 
//This is c
加入上述代码之后再次调用c.constructor(),则会打印出"This is c".这是因为c已自定义constructor属性"隐藏"了其原型对象中的constructor属性.当然js保证了读写的不对称性,也就是说读取一个对象的属性时有可能要从其原型对象中去读取,但写一个对象的属性时却从不涉及其原型对象,无论在一个对象加入或修改多少属性这都不影响其原型对象中属性的本来面目.比如这里c自定义了constructor属性,但这一行为并不影响其原型对象中constructor指向其构造函数这一事实,如果再创建一个对象且不自定义constructor属性,再调用constructor则依然调用对象的构造函数,例:
var b = new BaseClass();
b.constructor(); 
//调用BaseClass函数,输出This is BaseClass.

很容易理解js为什么这样做,因为一个对象的行为不能影响到其他对象,否则将会造成混乱.
        理解上述规则之后让我们看看js中是如何通过原型对象实现继承的.当我们创建一个对象时,可以把该对象看成是由2部分组成的,一部分存储了该对象自己定义的属性(称为A部分),而另一个部分则存储了其构造函数所定义的原型对象引用(称为B部分),例如这里的BaseClass.prototype.当读取对象的属性时可以分为以下2步:
1.js先检查该对象引用所指向的内存区域的A部分是否存在该属性,如果存在则读出.
2.如果没有则再从B部分存储的引用(BaseClass.prototype)所指向的内存区域中读取该属性.

从步骤2开始这就是个不断往上寻找的过程,因为BaseClass.prototype所指向的内存区域也会分为A和B两个部分,如果再A部分也不存在该属性,则又会从其B部分所指向的内存区域去寻找该属性,而该内存区域也有A和B两个部分,如果A部分仍然不存在,则还要从B部分所指向的内存区域去寻找该属性,直到达到最顶层的Object类.所以在无形当中就形成了一条链,也就是我们常说的原型链.如果理解了这个过程我想也就能了解原型对象了.下面简单分析下b.constructor();的调用过程便于加深理解.
1.js会在b所指向的内存区域A部分读取constructor属性.
2.当发现没有该属性后再从其类的构造函数原型对象引用所指向的内存区域读取该属性.因为原型对象引用初始时指向一Object对象内存区域(BaseClass.prototype = new Object();)
3.再从此Object对象的A部分寻找constructor属性.
4.没有找到该属性则从其类的原型对象即Object.prototype中去寻找constructor.
5.如果找到该属性则调用.
6.否则,到达链的顶端,返回.
到此能很清楚的知道js中是如何实现继承的,如果我们自定义的类不想继承自Object,则可以修改其prototype的指向,可以让其指向任意一个类,这样也就实现了继承自定义类,但js中所有的类都继承自Object类,所以原型链的关系仍然存在.

posted @ 2008-05-09 16:43 zhangchao 阅读(56) | 评论 (0)编辑 收藏
    项目中经常使用createDelegate()方法来创建代理函数,从而改变当前函数中this的作用域.看下了源码,发现是通过js中的apply()方法来实现,想想也只能通过apply()或者call()方法来实现,因为js中只有这2个方法提供了改变当前函数内部this作用域的功能.此外,Ext中很多地方用到了call()和apply()方法,要想看懂源码,则必须先搞清这2个方法的用法.
    createDelegate方法声明为:
 1createDelegate : function(obj, args, appendArgs){
 2        var method = this;
 3        return function() {
 4            var callArgs = args || arguments;
 5            if(appendArgs === true){
 6                callArgs = Array.prototype.slice.call(arguments, 0);
 7                callArgs = callArgs.concat(args);
 8            }
else if(typeof appendArgs == "number"){
 9                callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
10                var applyArgs = [appendArgs, 0].concat(args); // create method call params
11                Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
12            }

13            return method.apply(obj || window, callArgs);
14        }
;
15    }
,
其中obj表示函数内部this作用域的范围,args是数组,appendArgs是"Boolean或Number",如果appendArgs是Boolean型的且值为true,那么args参数将跟在调用代理方法时传入的参数后面组成数组一起传入当前方法,否则只传入args,如果appendArgs为Number型,那么args将插入到appendArgs指定的位置.
注意点:
1.函数内部的arguments关键字是函数执行时动态创建的,用来存储调用函数时所传入参数.这里第4行的arguments   并不指调用createDelegate方法所传入的参数(obj,args,appendArgs),而是指调用return function()时所传入的参数,即调用代理函数时所传入的参数.而args和appendArgs就是调用createDelegate方法时所传入的参数.总的来说,函数是在定义它的作用域中执行,而不是在调用它的作用域中执行.但也有特殊,比如这里的arguments.
2.call和apply的区别.
二者的第一个参数都是函数内部this的作用域,call的参数只能作为一串参数传入,而apply可以传入数组或arguments对象.如
fun.call(window,args0,args1,.....);
fun.apply(window,[1,2,3]);
但要注意的是apply方法传递到函数内部的参数实际也是作为一个个参数传递的.如果在fun内部测试arguments.length的话,则长度为3.同样,我们可以采用arguments[0],arguments[1],arguments[2]来分别引用1,2,3三个参数,而不是用arguments[0][0],arguments[0][1],arguments[0][2]来引用3个参数.这样才能解释11行的代码.
posted @ 2008-04-30 17:11 zhangchao 阅读(739) | 评论 (0)编辑 收藏
        Ext2.0中,Ext类有个namespace方法,该方法的作用是把传入的参数转换成对象.使用该方法的目的主要在于可以区分类名相同的类,这有点和java中的package作用类似.让我们先看下源码:
namespace : function(){
    
var a=arguments, o=null, i, j, d, rt;
    
for (i=0; i<a.length; ++i) {
        d
=a[i].split(".");
        rt 
= d[0];
            eval('
if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
        
for (j=1; j<d.length; ++j) {
            o[d[j]]
=o[d[j]] || {};
               o
=o[d[j]];
        }

    }

}
从代码可以看出,如果我们传入的字符串参数是以"."分割的,那么将会创建多个对象,比如:
Ext.namespace('system.corp');
则会创建2个对象,相当于执行了下面的代码:
system = {};
system.corp 
= {};
这样,我们在自定义类的时候就能这样使用:
Ext.namespace('system.corp');

system.corp.ManageCorp 
= function() {
    
//dosomething
}
如果还想定义一个同名的类,那么可以就使用不同的namespace来区分,这样2个类就不会冲突了:
Ext.namespace('system.admin');

system.admin.ManageCorp 
= function() {
    
//dosomething
}

此外,注意源码中"eval"方法的使用,如果有需要可以采用这种方式来解决问题.
posted @ 2008-03-19 22:24 zhangchao 阅读(107) | 评论 (4)编辑 收藏
    昨天在看Ext的源码时发现了以下代码attributes = attributes || {};一直以为js中的逻辑操作符返回的结果是boolean值即true或false,查了下文档才发现其实不然.
    js的逻辑操作符有3种,即逻辑与(&&),逻辑或(||)和逻辑非(!).逻辑非始终返回一个boolean值,即true或false.而逻辑与和逻辑或则不一定返回boolean值.查了下文档才明白逻辑与和逻辑或执行的规则:
逻辑与(&&):
1.先执行左边的表达式,得到该表达式的值.
2.尝试将该值转换成boolean.
3.如果2的结果是false,则返回1中得到的值(如果该值不是false,而是一个其他的值,比如是个对象,则将返回这个对象而不是false),执行完毕.
4.如果2的结果是true,执行右边表达式并得到值.
5.返回4中得到的值.

逻辑或(||):
1.先执行左边的表达式,得到该表达式的值.
2.尝试将该值转换成boolean.
3.如果2的结果是true,则返回1中得到的值,执行完毕.
4.如果2的结果是false,执行右边表达式并得到值.
5.返回4中得到的值.

总结:逻辑与如果左边是false,则整个表达式的值是左边表达式的值,如果为true,则整个表达式的值是右边表达式的值.
逻辑或如果左边是true,则整个表达式的值是左边表达式的值,如果为false,则整个表达式的值是右边表达式的值.
posted @ 2008-03-13 10:30 zhangchao 阅读(72) | 评论 (1)编辑 收藏
     摘要: 引子     编程世界里只存在两种基本元素,一个是数据,一个是代码。编程世界就是在数据和代码千丝万缕的纠缠中呈现出无限的生机和活力。     数据天生就是文静的,总想保持自己固有的本色;而代码却天生活泼,总想改变这个世界。      你看,数据代码间的关系与物质能量间的关系有着惊人的...  阅读全文
posted @ 2008-03-05 11:07 zhangchao 阅读(83) | 评论 (0)编辑 收藏
   今天是2月22日,爸爸的生日。等了许久的报告终于出来了,情况很好.我想这是爸爸收到的最贵重的生日礼物了,胜过任何的物质。今天我也很高兴,希望爸爸一天天的好起来.
posted @ 2008-02-22 23:27 zhangchao 阅读(15) | 评论 (0)编辑 收藏
仅列出标题