•合理使用面向对象编程
–提高复用性,提高可维护性,etc.
–并非提高软件质量的保证
•可以使用各种成熟的设计方式
–模式,etc
•不拘泥于使用OO方式扩展对象
–结合JavaScript的动态特性
–下一次课程
命名空间
•合理的组织大量的类型
–使开发人员能够方便地找到他们所需要的类型
–并非仅仅为了避免命名冲突
•可重复注册
–每个独立的脚本模块前都要注册命名空间以保证命名空间存在
Type.registerNamespace(“MyNamespace”);
类
•定义步骤:
–定义构造函数
–定义成员(方法、属性、事件)
–注册类
类–构造函数
•类的构造函数即为function定义
•通常用于初始化域变量
•私有成员使用下划线开头(无法真正封装)
–this._myPrivateField;
–this._myPrivateMethod();
类–构造函数
Type.registerNamespace("MyNamespace");
MyNamespace.MyClass= function(param1, ...){
this._myField= null;
...
}
类–定义方法
•基于prototype定义
MyNamespace.MyClass.prototype = {
myMethod1 : function() { ... },
myMethod2 : function(){
this.myMethod1(); // this保留字不可少
}
}
类–定义属性
•Microsoft AJAX Library的面向对象类型系统将add_和set_开头的方法认作属性
•避免定义只写属性,使用某个方法替代
类–定义属性
MyNamespace.MyClass = function(param1, ...) {
this._myProperty = null;
}
MyNamespace.MyClass.prototype = {
get_myProperty : function(){
return this._myProperty;
},
set_myProperty : function(value){
this._myProperty = value;
}
}
类–注册类
MyNamespace.MyClass = function(param1, ...) {
// …
}
MyNamespace.MyClass.prototype = {
// …
}
MyNamespace.MyClass.registerClass(
'MyNamespace.MyClass');
定义及使用类
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server" ScriptMode="Debug">
<Scripts>
<asp:ScriptReference Path="Employee.js" />
</Scripts>
</asp:ScriptManager>
<div id="info"></div>
<script language="javascript" type="text/javascript">
function display(text)
{
document.getElementById("info").innerHTML += (text + "<br />");
}
var jeffz = new MyNamespace.Intern("Jeffrey Zhao");
jeffz.set_year(3);
display(jeffz.getDescription());
var tom = new MyNamespace.Vendor("Tom");
tom.set_year(3);
display(tom.getDescription());
var jerry = new MyNamespace.FulltimeEmployee("Jerry");
jerry.set_year(5);
display(jerry.getDescription());
display("jeffz implements 'IEmployee' interface: " +
MyNamespace.IEmployee.isImplementedBy(jeffz));
var type = MyNamespace.EmployeeType.toString(tom.get_type());
display(String.format("{0} is a {1}.", tom.get_name(), type));
var all = MyNamespace.MyFlags.All;
display(MyNamespace.MyFlags.toString(all));
display(MyNamespace.MyFlags.parse("Item1, Item3"));
</script>
</form>
<asp:ScriptManager ID="ScriptManager1" runat="server" ScriptMode="Debug">
<Scripts>
<asp:ScriptReference Path="Employee.js" />
</Scripts>
</asp:ScriptManager>
<div id="info"></div>
<script language="javascript" type="text/javascript">
function display(text)
{
document.getElementById("info").innerHTML += (text + "<br />");
}
var jeffz = new MyNamespace.Intern("Jeffrey Zhao");
jeffz.set_year(3);
display(jeffz.getDescription());
var tom = new MyNamespace.Vendor("Tom");
tom.set_year(3);
display(tom.getDescription());
var jerry = new MyNamespace.FulltimeEmployee("Jerry");
jerry.set_year(5);
display(jerry.getDescription());
display("jeffz implements 'IEmployee' interface: " +
MyNamespace.IEmployee.isImplementedBy(jeffz));
var type = MyNamespace.EmployeeType.toString(tom.get_type());
display(String.format("{0} is a {1}.", tom.get_name(), type));
var all = MyNamespace.MyFlags.All;
display(MyNamespace.MyFlags.toString(all));
display(MyNamespace.MyFlags.parse("Item1, Item3"));
</script>
</form>
Employee.js
Type.registerNamespace("MyNamespace");
MyNamespace.EmployeeType = function()
{
throw Error.notImploemented();
}
MyNamespace.EmployeeType.prototype =
{
Intern : 0,
Vendor : 1,
FulltimeEmployee : 2
}
MyNamespace.EmployeeType.registerEnum("MyNamespace.EmployeeType");
MyNamespace.IEmployee = function()
{
throw Error.notImplemented();
}
MyNamespace.IEmployee.prototype =
{
calcaulateSalary : function()
{
throw Error.notImplemented();
},
get_type : function()
{
throw Error.notImplemented();
}
}
MyNamespace.IEmployee.registerInterface("MyNamespace.IEmployee");
MyNamespace.Employee = function(name)
{
this._name = name ? name : "[Anonymous]";
this._year = 0;
}
MyNamespace.Employee.prototype =
{
get_name : function()
{
return this._name;
},
get_year : function()
{
return this._year;
},
set_year : function(value)
{
this._year = value;
},
calculateSalary : function()
{
throw Error.notImplemented();
},
getDescription : function()
{
return String.format(
"{0} gets {1} yuan per month.",
this._name,
this.calculateSalary());
}
}
MyNamespace.Employee.registerClass("MyNamespace.Employee", null,
MyNamespace.IEmployee);
MyNamespace.Intern = function(name)
{
MyNamespace.Intern.initializeBase(this, [name]);
}
MyNamespace.Intern.prototype =
{
calculateSalary : function()
{
return 2000;
},
getDescription : function()
{
var description = MyNamespace.Intern.callBaseMethod(this, "getDescription");
return description + " What a poor intern!";
},
get_type : function()
{
return MyNamespace.EmployeeType.Intern;
}
}
MyNamespace.Intern.registerClass("MyNamespace.Intern", MyNamespace.Employee);
MyNamespace.Vendor = function(name)
{
MyNamespace.Vendor.initializeBase(this, [name]);
}
MyNamespace.Vendor.prototype =
{
calculateSalary : function()
{
return 5000 + 1000 * (this.get_year() - 1);
},
get_type : function()
{
return MyNamespace.EmployeeType.Vendor;
}
}
MyNamespace.Vendor.registerClass("MyNamespace.Vendor", MyNamespace.Employee);
MyNamespace.FulltimeEmployee = function(name)
{
MyNamespace.FulltimeEmployee.initializeBase(this, [name]);
}
MyNamespace.FulltimeEmployee.prototype =
{
calculateSalary : function()
{
return 15000 + 2000 * (this.get_year() - 1);
},
get_type : function()
{
return MyNamespace.EmployeeType.FulltimeEmployee;
}
}
MyNamespace.FulltimeEmployee.registerClass("MyNamespace.FulltimeEmployee", MyNamespace.Employee);
///////////////////////////////////////
MyNamespace.MyFlags = function()
{
throw Error.notImplemented();
}
MyNamespace.MyFlags.prototype =
{
Item1 : 1,
Item2 : 2,
Item3 : 4,
None : 0,
All : 7
}
MyNamespace.MyFlags.registerEnum("MyNamespace.MyFlags", true);
// Item1 + Item3
// Item1 | Item3 (preferred)
MyNamespace.EmployeeType = function()
{
throw Error.notImploemented();
}
MyNamespace.EmployeeType.prototype =
{
Intern : 0,
Vendor : 1,
FulltimeEmployee : 2
}
MyNamespace.EmployeeType.registerEnum("MyNamespace.EmployeeType");
MyNamespace.IEmployee = function()
{
throw Error.notImplemented();
}
MyNamespace.IEmployee.prototype =
{
calcaulateSalary : function()
{
throw Error.notImplemented();
},
get_type : function()
{
throw Error.notImplemented();
}
}
MyNamespace.IEmployee.registerInterface("MyNamespace.IEmployee");
MyNamespace.Employee = function(name)
{
this._name = name ? name : "[Anonymous]";
this._year = 0;
}
MyNamespace.Employee.prototype =
{
get_name : function()
{
return this._name;
},
get_year : function()
{
return this._year;
},
set_year : function(value)
{
this._year = value;
},
calculateSalary : function()
{
throw Error.notImplemented();
},
getDescription : function()
{
return String.format(
"{0} gets {1} yuan per month.",
this._name,
this.calculateSalary());
}
}
MyNamespace.Employee.registerClass("MyNamespace.Employee", null,
MyNamespace.IEmployee);
MyNamespace.Intern = function(name)
{
MyNamespace.Intern.initializeBase(this, [name]);
}
MyNamespace.Intern.prototype =
{
calculateSalary : function()
{
return 2000;
},
getDescription : function()
{
var description = MyNamespace.Intern.callBaseMethod(this, "getDescription");
return description + " What a poor intern!";
},
get_type : function()
{
return MyNamespace.EmployeeType.Intern;
}
}
MyNamespace.Intern.registerClass("MyNamespace.Intern", MyNamespace.Employee);
MyNamespace.Vendor = function(name)
{
MyNamespace.Vendor.initializeBase(this, [name]);
}
MyNamespace.Vendor.prototype =
{
calculateSalary : function()
{
return 5000 + 1000 * (this.get_year() - 1);
},
get_type : function()
{
return MyNamespace.EmployeeType.Vendor;
}
}
MyNamespace.Vendor.registerClass("MyNamespace.Vendor", MyNamespace.Employee);
MyNamespace.FulltimeEmployee = function(name)
{
MyNamespace.FulltimeEmployee.initializeBase(this, [name]);
}
MyNamespace.FulltimeEmployee.prototype =
{
calculateSalary : function()
{
return 15000 + 2000 * (this.get_year() - 1);
},
get_type : function()
{
return MyNamespace.EmployeeType.FulltimeEmployee;
}
}
MyNamespace.FulltimeEmployee.registerClass("MyNamespace.FulltimeEmployee", MyNamespace.Employee);
///////////////////////////////////////
MyNamespace.MyFlags = function()
{
throw Error.notImplemented();
}
MyNamespace.MyFlags.prototype =
{
Item1 : 1,
Item2 : 2,
Item3 : 4,
None : 0,
All : 7
}
MyNamespace.MyFlags.registerEnum("MyNamespace.MyFlags", true);
// Item1 + Item3
// Item1 | Item3 (preferred)