当前位置: 代码迷 >> JavaScript >> 初识ext懂得js的潮流
  详细解决方案

初识ext懂得js的潮流

热度:274   发布时间:2012-10-26 10:30:58.0
初识ext了解js的潮流
开篇,原本想大量引用网上对Ext-base.js文件的分析。但是经过大量的阅读国外的书籍发现,原来那人根本不懂什么是js面向对象程序设计。
参考书:
Apress出版的Pro.JavaScript.Design.Patterns
Professional.JavaScript.for.Web.Developers.2nd.Edition.2009
本文想通过一步一步的对javascript语法的进化来最后达到最ext-base.js的解析过程。
1. Javascript中的类
利用对javascript的常识,我认为js的设计应该如下:
/* Anim class. */
var Anim = function() {
...
};
Anim.prototype.start = function() {
...
};
Anim.prototype.stop = function() {
...
};
/* Usage. */
var myAnim = new Anim();
myAnim.start();
...
myAnim.stop();


定义了一个新的类Anim,委派了两个方法给prototype属性。所谓的prototype,我的理解是指针。实际上它和c++,c中指针的运行方法有微小的差别,但大致一样。详情请参考上面的两本书。
如果你喜欢把所有的属性和方法都装在类中。如下:
/* Anim class, with a slightly different syntax for declaring methods. */
var Anim = function() {
...
};
Anim.prototype = {
start: function() {
...
},
stop: function() {
...
}
};


通过以上的操作,产生一个新的概念:Encapsulation。我的理解:装箱。就是把所有的属性和方法放到类中。
值得谈到的是Javascript中的函数。在javascript中函数就是类。
函数的大部分概念和C++没有什么区别。值得注意的是匿名函数.
<html>
    <head>
        <title>String Example</title>
        <script type="text/javascript">
        	//在javascript中,函数都最好的对象
			//函数的大部分概念和C++没有什么区别。值得注意的是匿名函数
			//示例如下:
            /* An anonymous function, executed immediately. */
            (function(){
                var foo = 10;
                var bar = 2;
                alert(foo * bar);
            })();
			//这个函数的定义和执行并没有分配给任何变量。最后的()执行了这个函数。
			//他们是空的,但是并不是这种情况
            /* An anonymous function with arguments. */
            (function(foo, bar){
                alert(foo * bar);
            })(10, 2);
			//下例同第一个例子等价。不过将值给了一个内在的变量
            /* An anonymous function that returns a value. */
            var baz = (function(foo, bar){
                return foo * bar;
            })(10, 2);
            alert(baz);
			//匿名函数最有趣的应用时建立闭包。
			//闭包是一个受保护的变量空间,这就是说闭包函数可以在他们所定义的任意地方执行。不受函数体影响
            /* An anonymous function used as a closure. */
            var baz;
            (function(){
                var foo = 10;
                var bar = 2;
                baz = function(){
                    return foo * bar;
                };
            })();
			baz(); // baz can access foo and bar, even though it is executed outside of the class
        </script>
    </head>
    <body>
        <!-- Nothing in the body -->
		//在javascript中,函数都最好的对象
			//函数的大部分概念和C++没有什么区别。值得注意的是匿名函数
			//示例如下:
            /* An anonymous function, executed immediately. */
            (function(){
                var foo = 10;
                var bar = 2;
                alert(foo * bar);
            })();
			//这个函数的定义和执行并没有分配给任何变量。最后的()执行了这个函数。
			//他们是空的,但是并不是这种情况
            /* An anonymous function with arguments. */
            (function(foo, bar){
                alert(foo * bar);
            })(10, 2);
			//下例同第一个例子等价。不过将值给了一个内在的变量
            /* An anonymous function that returns a value. */
            var baz = (function(foo, bar){
                return foo * bar;
            })(10, 2);
            alert(baz);
			//匿名函数最有趣的应用时建立闭包。
			//闭包是一个受保护的变量空间,这就是说闭包函数可以在他们所定义的任意地方执行。不受函数体影响
            /* An anonymous function used as a closure. */
            var baz;
            (function(){
                var foo = 10;
                var bar = 2;
                baz = function(){
                    return foo * bar;
                };
            })();
			baz(); // baz can access foo and bar, even though it is executed outside of the class
    </body>
</html>


如果你使用装箱的写法,可以试试下面一种:
/* Add a method to the Function object that can be used to declare methods. */
Function.prototype.method = function(name, fn) {
this.prototype[name] = fn;
};
/* Anim class, with methods created using a convenience method. */
var Anim = function() {
...
};
Anim.method('start', function() {
...
});
Anim.method('stop', function() {
...
});
并修改method,让指针只记住类中各种方法的地址。即只给出链接。
/* This version allows the calls to be chained. */
Function.prototype.method = function(name, fn) {
this.prototype[name] = fn;
return this;
};
/* Anim class, with methods created using a convenience method and chaining. */
var Anim = function() {
...
};
Anim.method('start', function() {
...
}).
method('stop', function() {
...
});

在javascript中,所有的东西都是对象,所有的对象都是可变的。这就意味着你可以在类定义好,并实例化以后改变它。
<html> 
    <head> 
        <title>String Example</title> 
        <script type="text/javascript"> 
            //在javascript中,所有的东西都是对象
            //所有的对象都是可变的。
            //这就意味着你可以在类定义好,并实例化以后改变它。
            /* Class Person. */
            function Person(name, age){
                this.name = name;
                this.age = age;
            }
            
            Person.prototype = {
                getName: function(){
                    return this.name;
                },
                getAge: function(){
                    return this.age;
                }
            }
            /* Instantiate the class. */
            var alice = new Person('Alice', 93);
            var bill = new Person('Bill', 30);
			document.write("/* Instantiate the class. */<br/>");
			document.write("name: "+alice.name+";her age: "+alice.age+"<br/>");
			document.write("name: "+bill.name+";his age: "+bill.age+"<br/>");
            /* Modify the class. */
            Person.prototype.getGreeting = function(){
                return 'Hi ' + this.getName() + '!';
            };
			document.write("/* Modify the class. */<br/>");
			document.write("alice.getGreeting:"+alice.getGreeting()+"<br/>");
            /* Modify a specific instance. */
            alice.displayGreeting = function(){
                alert(this.getGreeting());
            }
			document.write("/* Modify a specific instance.  */<br/>alert(getGreeting)");
			alice.displayGreeting();
			
        </script> 
    </head> 
    <body> 
        <!-- Nothing in the body --> 
    </body> 
</html>

这种对象的可变性叫:自我检查introspection.你能实时的检查任何的属性和方法。这正因为对象可以实时改变,javascript才很少进行类型检查。
在javascript中,还有个根深蒂固的概念。闭包Closures。闭包就是在类中定义的函数。由于对象具有可变性,因此我们可以在类体意外去调用和改变类中定义的函数。
<html> 
    <head> 
        <title>String Example</title> 
        <script type="text/javascript"> 
            function foo(){
                var a = 10;
                function bar(){
                    a *= 2;
                }
                bar();
                return a;
            }
            
            document.writeln(foo());
        </script> 
    </head> 
    <body> 
        <!-- Nothing in the body --> 
    </body> 
</html> 

在javascript中,能够想到的创建对象的样式有三种。完全显示的对象(最简单但只提供公有成员)。使用括号标识方法和属性来区别私有成员(只是伪代码),详情请参考上面的书籍。最后是通过闭包的方法建立真正的私有成员。通过闭包实现私有成员。
有了闭包的特性,是可以实现真实的私有成员和公有成员的。在javascript中没有私有,公有的特性的。但是在实际的程序当中,我们往往要用到这些特性。这也是面向对象的重要部分之一。
<html> 
    <head> 
        <title>String Example</title> 
        <script type="text/javascript"> 
        var Book = function(newIsbn, newTitle, newAuthor){ // implements Publication
            // Private attributes.
            var isbn, title, author;
            
            // Privileged methods.
            this.getIsbn = function(){
                return isbn;
            };
            this.setIsbn = function(newIsbn){
                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(){
                return "ISBN:"+this.getIsbn() + "<br/>"
				+"Title:" + this.getTitle() + "<br/>"
				+"Author:" + this.getAuthor();
            }
        };
		var book = new Book('978-0261103283','pro javascript design pattern','Apress');
		document.write(book.display());
		
		//使用了更多的内存
		//很难被继承
        </script> 
    </head> 
    <body> 
        <!-- Nothing in the body --> 
    </body> 
</html> 

但是这么写的类,虽然是完成了类成员的私有,公有特性。但是这样的方法很难被继承,同时也造成大量的内存冗余。因为javascript中没有资源回收的机制。在类使用完毕之后,存储空间不会随之消失。我们还需要静态方法和真正的动态空间存储的方法。
<html> 
    <head> 
        <title>String Example</title> 
        <script type="text/javascript"> 
        var Book = (function(){
            // Private static attributes.
            var numOfBooks = 0;
            
            // Return the constructor.
            return function(newIsbn, newTitle, newAuthor){ // implements Publication
                // Private attributes.
                var isbn, title, author;
                // Private static method.
                function checkIsbn(isbn){
                    if (isbn) {
                        return true;
                    }
                    else {
                        return false;
                    }
                }
                // 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.
                numOfBooks++; // Keep track of how many Books have been instantiated
                // with the private static attribute.
                if (numOfBooks > 50) 
                    throw new Error('Book: Only 50 instances of Book can be ' +
                    'created.');
                this.setIsbn(newIsbn);
                this.setTitle(newTitle);
                this.setAuthor(newAuthor);
            }
        })();
        // Public static method.
        Book.convertToTitle = function(inputString){
            return inputString + "[us]";
        };
        // Public, non-privileged methods.
        Book.prototype = {
            display: function(){
                return "ISBN:" + this.getIsbn() + "<br/>" +
                "Title:" +
                this.getTitle() +
                "<br/>" +
                "Author:" +
                this.getAuthor();
            }
        };
        var book = new Book('978-0261103283', Book.convertToTitle('pro javascript design pattern'), 'Apress');
        document.write(book.display());
        </script> 
    </head> 
    <body> 
        <!-- Nothing in the body --> 
    </body> 
</html> 

静态方法的实现,实际上是利用匿名函数,在内存的堆中申请一片空间。类中只记录这片存储区域的地址。类调用完成,匿名函数随之消失。同时类中申请的静态变量保留了下来。
有了上面面向对象的公有私有成员和方法,对象可变性的概念。来看看js中继承的实现
Javascript的语法提供使用基于对象的继承。我们可以用它来模拟基于类的继承。
<html> 
    <head> 
        <title>String Example</title> 
        <script type="text/javascript"> 
            /* Class Person. */
            function Person(name){
                this.name = name;
            }
            
            Person.prototype.getName = function(){
                return this.name;
            }
            /* Class Author. */
			//建立一个类,继承于其他类
            function Author(name, books){
			//首先,建立构造器函数,call父类的构造函数,传递参数	
                Person.call(this, name); // Call the superclass's constructor in the scope of this.
                this.books = books; // Add an attribute to Author.
            }
            //当你调用new操作符,很多事已经为你准备好。首先一个空的object对象已经建立。
			//构造器函数调用空对象的scope chain
            Author.prototype = new Person(); // Set up the prototype chain.
            Author.prototype.constructor = Author; // Set the constructor attribute to Author.
            Author.prototype.getBooks = function(){ // Add a method to Author.
                return this.books;
            };
            
            //实例测试
            var author = [];
            author[0] = new Author('Dustin Diaz', ['JavaScript Design Patterns']);
            author[1] = new Author('Ross Harmes', ['JavaScript Design Patterns']);
            
            document.write(author[0].getName()+' ' +author[0].getBooks()+"<br/>");
			document.write(author[1].getName()+' ' +author[1].getBooks());
			
        </script> 
    </head> 
    <body> 
        <!-- Nothing in the body --> 
    </body> 
</html> 

尽管代码相当简单,利用prototype这个指针进行地址的链接。但是它却是个很复杂的话题。javascript没有继承关键字。与之替代的,每个object对象都有prototype属性。这个属性指向另一个对象或者null。当对象成员被读取,javascript通过prototype读取该对象。如果它在现在的对象中不存在,javascript会读取每个对象的prototype。直到读到该对象或者null,这和其他的面向对象语言完全不一样。这种方法使得多个子类被实例化的同时,父类也同样被实例化很多次。浪费了内存。在子类实例化的情况下,实例化改变父类,子类会受到很大影响。
基于以上原因,必须要改变继承的方式。
<html> 
    <head> 
        <title>String Example</title> 
        <script type="text/javascript"> 
            /* Extend function, improved. */
            function extend(subClass, superClass){
                var F = function(){
                };
                F.prototype = superClass.prototype;
                subClass.prototype = new F();
                subClass.prototype.constructor = subClass;
                subClass.superclass = superClass.prototype;
                if (superClass.prototype.constructor == Object.prototype.constructor) {
                    superClass.prototype.constructor = superClass;
                }
            }
            
            /* Class Person. */
            function Person(name){
                this.name = name;
            }
            
            Person.prototype.getName = function(){
                return this.name;
            }
            /* Class Author. */
            function Author(name, books){
                Author.superclass.constructor.call(this, name);
                this.books = books;
            }
            
            extend(Author, Person);
            Author.prototype.getBooks = function(){
                return this.books;
            };
            //改变Author类
            Author.prototype.getName = function(){
                var name = Author.superclass.getName.call(this);
                return name + ', Author of ' + this.getBooks().join(', ');
            };
            
            //实例测试
            var author = [];
            author[0] = new Author('Dustin Diaz', ['JavaScript Design Patterns']);
            author[1] = new Author('Ross Harmes', ['JavaScript Design Patterns']);
            
            document.write(author[0].getName() + "<br/>");
            document.write(author[1].getName());
        </script> 
    </head> 
    <body> 
        <!-- Nothing in the body --> 
    </body> 
</html> 

继承方式已经实现。但是离ext-base.js的目标还差得远。在此,先提出一个概念:Prototypal Inheritance,我的理解为:指针型继承。指针型继承非常不同。我们发现最好的去思考它的方法是忘掉一切关于类和实例化的方法。只考虑对象本身,典型创建对象有两种方法
a.定义对象结构,使用类声明
b.实例化类,并创建对象(网上把它叫做对象直接量)
通过实例化类来创建的对象是拷贝所有实例化的属性,连接所有实例化方法的地址在指针型继承中,这样做的优点是你能很简单的建一个类。这个类可以被其他类重用。
<html> 
    <head> 
        <title>String Example</title> 
        <script type="text/javascript"> 
			//函数与函数间指针的传递
            /* Clone function. */
            function clone(object){
                function F(){
                }
                F.prototype = object;
                return new F;
            }
            
            /*
             * 指针型继承Prototypal Inheritance
             * 指针型继承非常不同。我们发现最好的去思考它的方法是忘掉一切关于类和实例化的方法。只考虑对象本身
             * 典型创建对象有两种方法
             * a.定义对象结构,使用类声明
             * b.实例化类,并创建对象
             * 通过实例化类来创建的对象是拷贝所有实例化的属性,连接所有实例化方法的地址
             * 在指针型继承中,你能很简单的建一个类。这个类可以被其他类重用
             */
            /* Person Prototype Object. */
            var Person = {
                name: 'default name',
                getName: function(){
                    return this.name;
                }
            };
            //简单对象的继承和测试
            var reader = clone(Person);
			document.write("<h5 style='color:red'>simple object inherited and testing</h5>");
            document.write(reader.getName() + "<br/>"); // This will output 'default name'.
            reader.name = 'John Smith';
            document.write(reader.getName() + "<br/>"); // This will now output 'John Smith'.
            
			
            /* Author Prototype Object. */
            var Author = clone(Person);
            Author.books = []; // Default value.
            Author.getBooks = function(){
                return this.books;
            }
            
            var author = [];
            author[0] = clone(Author);
            author[0].name = 'Dustin Diaz';
            author[0].books = ['JavaScript Design Patterns'];
            author[1] = clone(Author);
            author[1].name = 'Ross Harmes';
            author[1].books = ['JavaScript Design Patterns'];
			document.write("<h5 style='color:red'>Author object inherited and testing</h5>");
            document.write(author[0].getName() + ' ' + author[0].getBooks() + "<br/>");
            document.write(author[1].getName() + ' ' + author[1].getBooks() + "<br/>");
            
            /*
             * 异步读写父类成员
             * 为了有效的使用指针型继承,我们必须忘掉所有传统的继承方式。这就是所要忘记的方式之一。
             * 在传统的继承里,每个Author类都拷贝了books数组。你可以通过author[1].books.push('New Book Title')添加到数组
             * 这种方式不能用于指针型继承。因为prototype链起了作用
             * clone函数并不是object对象的prototype完全独立的拷贝。
             * 当你读取author[1].name,你只是得到从prototype那里保存的连接。并没有得到实例的值
             * 当你写一个author[1].name,实际是为author[1]对象添加了一个新的属性
             */
            var authorClone = clone(Author);
			document.write("<h5 style='color:red'>Symmetrical Reading and Writing of Inherited Members</h5>");
            document.write("Name="+authorClone.getName() + "<br/>"); // Linked to the primative Person.name, which is the string 'default name'.
            document.write("Books="+authorClone.getBooks() + "<br/>");
            authorClone.name = 'new name'; // A new primative is created and added to the
            // authorClone object itself.
            document.write("Name="+authorClone.getName() + "<br/>"); // Now linked to the primative authorClone.name, which
            // is the string 'new name'.
            authorClone.books.push('new book'); // authorClone.books is linked to the array
            document.write("Books="+authorClone.getBooks() + "<br/>");
            // Author.books. We just modified the
            // prototype object's default value, and all
            // other objects that link to it will now
            // have a new default value there.
            authorClone.books = []; // A new array is created and added to the authorClone
            // object itself.
            authorClone.books.push('a new book to array'); // We are now modifying that new array.
            document.write("<h5 style='color:red'>Asymmetrical Reading and Writing of Inherited Members</h5>");
            document.write(authorClone.getName() + ' ' + authorClone.getBooks() + "<br/>");
        </script> 
    </head> 
    <body> 
        <!-- Nothing in the body --> 
    </body> 
</html> 

通过Prototypal Inheritance的指针继承,我们体会到一种设计模式:骨架模式。骨架模式就是基类设置好所有的属性和方法,并赋默认值。子类需要自己的方法可以任意的添加。这里引出一个概念:异步读写父类成员。为了有效的使用指针型继承,我们必须忘掉所有传统的继承方式。这就是所要忘记的方式之一。在传统的继承里,每个Author类都拷贝了books数组。你可以通过author[1].books.push('New Book Title')添加到数组。这种方式不能用于指针型继承。因为prototype链起了作用。 clone函数并不是object对象的prototype完全独立的拷贝。当你读取author[1].name,你只是得到从prototype那里保存的连接。并没有得到实例的值。当你写一个author[1].name,实际是为author[1]对象添加了一个新的属性。通俗的讲,父类给出了骨架,子类去加肉。
但是有时候,指针对象会有子对象包含其中。如果你想重写子对象某一个单一的方法,你必须重建整个对象。这可以通过将子对象复制给空对象实现。但是这要求被克隆的对象必须明确子对象的结构和默认值。为了保持各对象之间的低耦合度,任何复杂的子对象都应该用固定的方法创建。工厂模式因此而产生。
<html> 
    <head> 
        <title>String Example</title> 
        <script type="text/javascript"> 
            /* Clone function. */
            function clone(object){
                function F(){
                }
                F.prototype = object;
                return new F;
            }
            
            /*
             * 有时候,指针对象会有子对象包含其中。
             * 如果你想重写子对象某一个单一的方法,你必须重建整个对象
             * 这可以通过将子对象复制给空对象实现
             * 但是这要求被克隆的对象必须明确子对象的结构和默认值
             * 为了保持各对象之间的低耦合度,任何复杂的子对象都应该用固定的方法创建
             * 工厂模式因此而产生
             */
            var CompoundObject = {};
            CompoundObject.string1 = 'default value';
            CompoundObject.createChildObject = function(){
                return {
                    bool: true,
                    num: 10
                }
            };
            CompoundObject.childObject = CompoundObject.createChildObject();
            var compoundObjectClone = clone(CompoundObject);
            compoundObjectClone.childObject = CompoundObject.createChildObject();
            compoundObjectClone.childObject.num = 5;
			document.write(compoundObjectClone.string1 + "<br/>");
			document.write(compoundObjectClone.childObject.num);
        </script> 
    </head> 
    <body> 
        <!-- Nothing in the body --> 
    </body> 
</html> 

到此,ext-base.js的所有概念都有了。下面开始具体分析extend类
<html> 
    <head> 
        <title>Extend Example</title> 
        <script type="text/javascript"> 
        	//Ext类的第一个细胞原型
			//骨架模式。采用Prototypal Inheritance的指针继承方式
        	//ext类是用隐私的实例化类开始进行构造的。
            Ext = {
                version: '3.0'
            };
			//Ext类之对象拷贝函数。实现对象与对象之间的直接复制。
			/*
			 * in这个操作符在IE中无法识别非枚举属性
			 * 以下非枚举属性toString(),hasOwnProperty() ,propertyIsEnumerable() , toLocaleString() , valueOf()
			 * Ext的解决方法是用overrides重新写了apply这个函数,其中所有toString的方法全部由object类的方法覆盖。
			 * apply的另一变形是applyif。但是如果某属性存在,则不会被覆盖。
			 */
            Ext.apply = function(o, c, defaults){
                // no "this" reference for friendly out of scope calls
                if (defaults) {
                    Ext.apply(o, defaults);
                }
                if (o && c && typeof c == 'object') {
                    for (var p in c) {
                        o[p] = c[p];
                    }
                }
                return o;
            };
            Ext.apply(Ext, {
				//判断类型v是否是object类
                isObject: function(v){
                    return v && typeof v == "object";
                },
				//Ext类之继承属性
				/*
				 * 闭包:
				 * 1、作为一个函数变量的一个引用 - 当函数返回时,其处于激活状态。
				 * 2、一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
				 */
				//Ext是个匿名函数
                extend: function(){
                    // inline overrides
					//这句是将所有的supperclass,subclass,overrides方法拷贝到io类备用。
					
                    var io = function(o){
                        for (var m in o) {
                            this[m] = o[m];
                        }
                    };
                    var oc = Object.prototype.constructor;
                    
                    return function(sb, sp, overrides){
					//如果传递进来的第二个参数是object。
					//拷贝子类到overrides类,如果overrides里面有个constructor属性,
					//就用overrides的constructor当作子类的构造函数。
					//否则,创建个新的function,里面包含一句话,就是"sp.apply(this, arguments);",
					//这个又是闭包的一个应用,在退出extend方法之后并没有释放局部变量sp的内存空间。
					//子类拷贝完成
                        if (Ext.isObject(sp)) {
                            overrides = sp;
                            sp = sb;
                            sb = overrides.constructor != oc ? overrides.constructor : function(){
                                sp.apply(this, arguments);
                            };
                        }
						//var F=function(){},定义一个空函数,里面没有属性。
						//F.prototype=sp.prototype
						//sbp=new F()把F.prototype也就是sp.prototype里面的东西拷贝到sb.prototype
						//同时,因为F是个没有任何属性的函数,所以不需要再delete任何东西。
						//将超类拷贝到了sbp。
						//以父类为骨架,并将更多的方法和属性添加到子类中,代码值得借鉴
                        var F = function(){
                        }, sbp, spp = sp.prototype;
                        
                        F.prototype = spp;
                        sbp = sb.prototype = new F();
						//sb.prototype.constructor是F(),所以sbp.constructor=sb
                        sbp.constructor = sb;
                        sb.superclass = spp;
                        if (spp.constructor == oc) {
                            spp.constructor = sp;
                        }
                        sb.override = function(o){
                            Ext.override(sb, o);
                        };
                        sbp.superclass = sbp.supr = (function(){
                            return spp;
                        });
                        sbp.override = io;
                        Ext.override(sb, overrides);
                        sb.extend = function(o){
                            Ext.extend(sb, o);
                        };
                        return sb;
                    };
                }(),
				//和apply一样的功能,复制对象。如果子类重写了toString,则覆盖父类。
                override: function(origclass, overrides){
                    if (overrides) {
                        var p = origclass.prototype;
                        Ext.apply(p, overrides);
                        if (Ext.isIE && overrides.toString != origclass.toString) {
                            p.toString = overrides.toString;
                        }
                    }
                }
            });
			//实例测试
			//申请一个新的类S
            function S(){
            }
            //S中两个变量s,s1
            S.prototype.s = "s";
            S.prototype.s1 = "s1";
			//申请一个类C
			//C中两个变量c,c1
            function C(){
                this.c = "c";
                this.c1 = "c1";
            }
            //C继承S基类,并重写s1
            Ext.extend(C, S, {
                s1: "by c overload"
            });
			//实例化C
            var c = new C();
            alert(c.s); //s   
            alert(c.s1); //by c overload 
        </script> 
    </head> 
    <body> 
        <!-- Nothing in the body --> 
    </body> 
</html> 


1 楼 laitaogood 2009-09-29  
太长了,没看完,但是注释写的非常好,哈哈
  相关解决方案