<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>js 类与对象</title>
</head>
<script type="text/javascript">
/*
//(1) 用定义函数的方式来定义类
function class1(){
alert("构造函数")
//类成员的定义及构造函数
}
//这里的class1既是一个函数 也是一个类,可以将它理解成类的构造函数,负责初始化工作
//(2) 使用new 操作符来获得一个类的实例
var d = new Date();
var obj1 = new class1();//会提示"构造函数"
alert(typeof(obj1))
//在js中,类与函数是一个概念
//如果这个函数没有初始化类成员,则会返回一个空的对象
//(3)使用[] 引用对戏的属性与方法
//使用方法: 1 对象.属性(方法) 2 对象.["属性(方法)"]
var arr = new Array();
arr.push("abc");
arr["push"]("def");
alert(arr.length)
//alert(arr["length"])
//js对象就是一组属性(方法)的集合
//这种用法适合 不确定具体要引用哪个属性(方法)的情况
function User(){
this.age = 22;
this.name = "shi";
}
var user = new User();
//动态显示不确定的属性值
function show(slt){
if(slt.selectedIndex != 0){
alert(user[slt.value]); //显示user对象中属性为slt.value的属性值 - 使用[]
//alert(eval("user." + slt.value));// -- 使用eval()
}
}
//使用[] 还可以使用 非标识符的字符串来作为属性名(如标识符中不允许以数字开头 或 有空格)
user["my name"] = "robert";
//alert( user["my name"])
//(4)动态添加 修改 删除对象的属性与方法
var man = new Object();
//添加与修改属性
man.name = "jack"
//添加与修改方法
man.sayHello = function(){
alert("hello, my name is " + this.name)
}
man.sayHello();
//删除属性
man.name = undefined
//删除方法
man.sayHello = undefined
//(5)使用{} 来创建无类型对象
var woman = {
name: "mary",
sayHello: function(){
alert("hello, my name is " + this.name)
}
}
//(6) prototype 原型对象
//每个函数都是一个对象,他们对应的类是“Function”,但是他们身份特殊,每个函数对象都具有一个子对象prototype
//prototype 表示了该函数的原型,而函数也是类,则prototype 表示了一个类的成员的集合
//空类
function class2(){
}
class2.prototype.method1 = function(){
alert("这是类的方法")
}
var obj3 = new class2();
obj3.method2 = function(){
alert("这是成员的方法")
}
obj3.method1();//调用类方法,只要是class2的对象都可以调用
obj3.method2();//调用对象方法,仅仅是obj3调用
//(7)认识函数对象 Function
//内部对象: Function、 Date、 Array、 String -- 通过new Array()这样的语句返回一个对象,js内部有一套机制来初始化返回的对象,而不是由用户来指定对象的构造方式
//用户自定义对象
//js中,函数对象对应的类型是Function,可以使用new Function()来创建函数对象
function myfun(a, b){
return a + b;
}
//等价于
var myfun1 = new Function("a", "b", "return a + b;")
//对比数组对象
var myarr = [];
var myarr1 = new Array();
//内部对象
alert(typeof(Function));//function
alert(typeof(new Function()));//function
alert(typeof(Array));//function
alert(typeof(new Array()));//object
alert(typeof(Object));//function
alert(typeof(new Object()));//object
alert(typeof(Date));//function
alert(typeof(new Date()));//object
//(8)prototype
//函数的prototype扩展 -- 所有函数对象的扩展
Function.prototype.method3 = function(){
alert("function 扩展")
}
function xfun(){
}
xfun.method3();
xfun.method3.method3(); //其中 xfun.method3也是函数对象,递归思路
//Object的prototype扩展 -- 所有js对象(包括函数对象)的扩展
Object.prototype.getType = function(){
alert(typeof(this))
}
var x = new Array();
var y = function(){}
x.getType();//Object
y.getType();//function
//(9)将函数作为参数传递
function xx(){
alert("xx")
}
function ff(xfun){
xfun();
};
ff(xx)//将函数作为参数传递
//(10)传递给函数的隐含参数 arguments
function showargs(){
for(var i=0; i < arguments.length; i++){
alert(arguments[i])
}
}
showargs(1,2,3,4,5)
//arguments的另一个属性callee,他表示对函数本身的引用,这有利于实现无名函数的递归 或者保证函数的封装性,例如使用递归来计算1到n的整数之和
var sum = function(n){
if(1==n){
return 1;
}
return n + sum(n -1);
}
alert(sum(100))
var sum1 = function(n){
if(1==n){
return 1;
}
return n + arguments.callee(n -1);
}
alert(sum1(100))
//(10)函数的apply、call方法 和 length属性
//Function.prototype.apply(this对象, 参数数组)
//Function.prototype.call(this对象, 参数1, 参数2, ...)
//作用是将函数绑定到另外一个对象上 运行
function f1(){
this.p = "f1";
this.A = function(arg){
alert(this.p + "|" +arg)
}
}
function f2(){
this.p = "f2";
this.B = function(arg){
alert(this.p + "|" +arg)
}
}
var obj1 = new f1();
var obj2 = new f2();
obj1.A("by A") //f1 by A
obj2.B("by B") //f2 by B
obj1.A.apply(obj2, ["by A"]) //f2 by A
obj2.B.apply(obj1, ["by B"]) //f1 by B
obj1.A.call(obj2, "by A") //f2 by A
obj2.B.call(obj1, "by B") //f1 by B
//函数对象属性length -- 函数定义的参数个数
//arguments.length -- 实际传递的参数个数
alert(f1.length)
//(11)this 表示当前运行该函数的对象
var obj = new Object();
obj.p = "xxx";
obj.getP = function(){
alert(this.p); //this 指向的是 obj对象
}
//(12)类的实现机制
//使用new 创建对象的过程
//1 当解析器遇到new 操作符则创建一个空对象
//2 开始运行class1这个函数,并将其中的this指针指向这个新建的对象
//3 因为当给对象不存在的属性赋值时,解析器就会为对象创建该属性,这样函数的执行就是初始化这个对象的过程,即实现了构造函数的作用
//4 当函数执行完后,new 操作符就会返回初始化后的对象
//类成员
function class1(){
this.p = "b";
this.method1 = function(){
alert("class1方法:" + this.p)
}
}
//使用prototype对象来定义类成员
//当new 一个function时,该prototype对象的成员将自动赋予所创建的对象
//new执行的过程
//1 创建一个新对象,将this指针指向他
//2 将函数的prototype对象的所有成员都赋给这个新建的对象
//3 执行函数体,对这个对象进行初始化操作
//4 返回创建的对象
//类成员 -- 将成员保存在 class1.prototype原型对象中
class1.prototype.showProp = function(){
this.p = 'a'
alert("prototype方法:" + this.p)
}
//注意:原型对象的定义必须在创建类实例的语句之前,否则他将不起作用
var oo = new class1;
oo.method1();
oo.showProp();
//js类的设计模式
//定义一个类class1
function class1(){
//构造函数
}
//通过指定prototype对象来实现类的成员定义
class1.prototype={
prop1: "tt",
method1: function(){}
}
//(13) 类的成员 + 静态成员
function class1(){
this.pp = "非静态成员";
}
class1.pp = "静态成员"
//如果要为每一个函数对象添加通用的静态方法,可以通过函数对象的prototype来实现
Function.prototype.showArgCount = function(){
alert(this.length)//显示函数定义的参数个数
}
function tt(a){}
tt.showArgCount()
//示例 prototype-1.3.1.js
//将函数作为一个对象的方法来运行
Function.prototype.bind = function(object){
var _method = this; //指的是实际运行的某个函数
return funtion(){
_method.apply(object, arguments); //将函数绑定到object上来运行
}
}
//将函数作为事件监听器
Function.prototype.bindAsEventListener = function(object){
var _method = this; //指的是实际运行的某个函数
return funtion(event){
_method.apply(object, evnet || window.evnet); //将函数绑定到object上来运行, 使用evnet || window.evnet作为参数,将会在函数体中处理事件对象evnet || window.evnet
}
}
//(14)使用 for(.. in ..)实现反射机制
//反射机制 是指程序在运行时能够获得自身的信息,如一个对象在运行时知道自己有哪些属性与方法
function showProp(obj){
for(var p in obj){
alert(p + ":" + obj[p])
}
}
var aa = { name: "aa", age: 13}
showProp(aa)
function setStyle(obj, _style){
obj.style = _style;
}
function addStyle(obj, _style){
for(var p in _style){
obj.style[p] = _style[p]
}
}
//(15)利用共享prototype实现继承 -- 不能彻底的实现继承
//定义class1
function class1(){
}
//定义class1成员
class1.prototype={
m1: function(){
alert(1);
}
}
//定义class2
function class2(){
}
//让class2继承class1 -- 共享prototype
class2.prototype = class1.prototype
//重载基类的方法
class2.prototype.m1 = function(){
alert(2);
}
//调用重载方法
var obj1 = new class1();
var obj2 = new class2();
obj1.m1();//2
obj2.m1();//2
//可见 class1与class2的prototype是完全相同,是对同一个对象的引用,也就是共享的prototype
//alert(typeof(obj1))//object
//alert(typeof(obj2))//object
alert(obj1 instanceof class1)//true
alert(obj2 instanceof class1)//true
alert(obj1 instanceof class2)//true
alert(obj2 instanceof class2)//true
//可见instanceof操作符的执行机制 -- 就是判断一个对象是否是一个prototype的实例
//(16)利用反射机制与prototype来实现继承
//定义class1
function class1(){
}
//定义class1成员
class1.prototype={
m1: function(){
alert(1);
}
}
//定义class2
function class2(){
}
//让class2继承class1 -- 复制prototype
for(var p in class1.prototype){
class2.prototype[p] = class1.prototype[p]
}
//重载基类的方法
class2.prototype.m1 = function(){
alert(2);
}
//调用重载方法
var obj1 = new class1();
var obj2 = new class2();
obj1.m1();//1
obj2.m1();//2
//(17)js扩展 -- 继承的方法
Function.prototype.inherit = function(baseClass){ //Function在js中可以充当类,this就是指类本身
for(var p in baseClass.prototype){
this.prototype[p] = baseClass.prototype[p];//复制基类的prototype
}
}
//定义class1
function class1(){
}
//定义class1成员
class1.prototype={
m1: function(){
alert(1);
}
}
//定义class2
function class2(){
}
class2.inherit(class1)
var obj2 = new class2();
obj2.m1();//1
//(18) prototype-1.3.1框架中雷继承实现机制
//为Object添加静态方法: extend
Object.extend = function(destination, source){
for(var property in source){
destination[property] = source[property];//复制对象属性
}
return destination;
}
//通过Object类为每个对象添加方法 extend
Object.prototype.extend = function(obj){
return Object.extend.apply(this, [this, obj]);
}
function class1(){}
function class2(){}
//让class2 继承于class1 并定义新成员
//实际上是将class1的对象的属性复制到class2.prototype, 因此class1与class2 没有共享prototype
class2.prototype = (new class1()).extend({
method: function(){
alert(2);
}
})
//以下的继承有误:class1与class2 是共享同一个prototype
//class2.prototype = class1.prototype.extend({
// method: function(){
// alert(2);
// }
//})
var obj = new class2()
obj.method();
//(19) 抽象类与虚函数
//在面向对象语言中,抽象类的虚方法必须先被声明,但可以在其他方法中被调用
//js 中,虚方法可以看做该类中没有定义的方法,但是已通过this指针使用了,同时,js中的虚函数不需经过声明,就可直接使用
//为Object添加静态方法: extend
Object.extend = function(destination, source){
for(var property in source){
destination[property] = source[property];//复制对象属性
}
return destination;
}
//通过Object类为每个对象添加方法 extend
Object.prototype.extend = function(obj){
return Object.extend.apply(this, [this, obj]);
}
//定义一个抽象的基类base,无构造函数
function base(){}
base.prototype = {
initialize: function(){
this.oninit(); // 调用一个虚方法
}
}
//定义class1
function class1(){
//构造函数
}
//让class1继承base,并实现其中的oninit方法
class1.prototype = (new base()).extend({
oninit: function(){//实现抽象基类中的oninit虚方法
alert("nothing")
}
})
var obj = new class1();
obj.initialize()
//(20)使用抽象类的示例
//prototype-1.3.1 定义了一个类的创建模型
//Class是一个全局对象,有一个方法create,用于返回一个类
var Class = {
create: function(){
return function(){ //返回一个类
this.initialize.apply(this, arguments) //initialize 虚方法在构造函数中被调用,在每次创建类实例都会被调用
}
}
}
//var class1 = Class.create();//获得一个新的类
//类似于
function class1(){
this.initialize.apply(this, arguments)
//this.initialize = function(){
// alert("hello")
//}
}
//总结: initialize 是虚函数,必须要在prototype中实现
class1.prototype.initialize = function(){
alert("hello")
}
var obj = new class1();
//(21) 最简单的事件模式 -- 将一个类的方法成员定义成事件
function class1(){
//构造函数
}
class1.prototype={
show: function(){
this.onshow(); //触发onshow事件
},
onshow: function(){} //定义事件接口
}
var obj = new class1();
obj.onshow = function(){ //创建obj的onshow事件处理函数
alert("onshow evnet")
}
obj.show();
//(22)为事件处理函数传递参数
//因为事件机制仅穿阿迪一个函数的名称,不带有任何参数的信息,所以无法传递参数进去
//不考虑怎么将参数传进去,而是考虑如何构建一个无需参数的事件处理函数,该程序是根据由参数的事件处理程序来构建的,是一个外层的封装
//将有参数的函数 封装为 无参数的函数
function createFunction(obj, strFunc){
var args = []; //定义args 用于存储传递给事件处理函数的参数
if(!obj){
obj = window; //如果没有obj参数,则认为是全局函数,则 obj = window;
}
//得到传递给事件处理函数的参数
//-- 利用arguments对象处理第二个参数以后的隐式参数,即未定义形参的参数,并在调用事件处理程序时将这些参数传递进去
for(var i = 2; i < arguments.length; i++){ // i 从2 开始,是因为要剔除显式声明的两个参数
args.push(arguments[i]);
}
//用无参数函数来封装事件处理程序的调用
return function(){
obj[strFunc].apply(obj, args);//将参数传给指定的事件处理程序
}
}
//调用的例子
//一个事件处理程序是
//sobj.eventHandler = function(arg1, arg2){
//事件处理函数
//}
//调用形式为
//createFunction(sobj, "eventHandler", arg1, arg2)
//具体的调用过程
function class1(){
//构造函数
}
class1.prototype={
show: function(){
this.onshow(); //触发onshow事件
},
onshow: function(){} //定义事件接口
}
var obj = new class1();
//创建事件处理函数
function xxonshow(username){
alert("hello," + username)
}
//绑定事件处理函数
var username = "shijianhang"
obj.onshow = createFunction(null, "xxonshow", username)
username = "robert"
//触发事件
obj.show();
//(23)自定义事件支持多绑定 -- 绑定多个事件处理函数
function class1(){
//构造函数
}
class1.prototype={
show: function(){
//触发onshow事件 -- 如果有时间绑定,则循环onshow数组
if(this.onshow){
for(var i = 0; i < this.onshow.length; i ++){
this.onshow[i]();//调用事件处理函数
}
}
},
//定义事件接口
attachOnShow: function(_eHandler){
if(!this.onshow){
this.onshow = [];//用数组来存储绑定的事件处理程序的引用
}
this.onshow.push(_eHandler)
}
}
var obj = new class1();
function onshow1(){ alert(1); }
function onshow2(){ alert(2); }
//绑定事件
obj.attachOnShow(onshow1)
obj.attachOnShow(onshow2)
//触发事件
obj.show();
*/
//(24)使用cookie
var Cookie = {
setCookie: function(name, value, option){
//用于存储赋值给 document.cookie 的 cookie格式字符串
var str = name + "=" + escape(value);//设置值
if(option){//设置选项
//如果设置了过期时间
if(option.expireDays){
var date = new Date();
var ms = option.expireDays * 24 * 3600 * 1000; //天数 -- 毫秒
date.setTime(date.getTime() + ms);
str += "; expires=" + date.toGMTString();
}
if(option.path) {
str += "; path=" + option.path; // 设置访问路径
}
if(option.domain) {
str += "; domain=" + option.domain; // 设置访问主机
}
if(option.secure) {
str += "; path=" + option.secure; // 设置安全性
}
}
document.cookie = str;
},
getCookie: function(name){
var cookieArray = document.cookie.split("; ");//分隔成cookie的名值对
var cookie = new Object();
for(var i = 0; i < cookieArray.length; i++){
var arr = cookieArray[i].split("="); //将名与值分开
if(arr[0] == name){
return unescape(arr[1]); //如果是指定的cookie,则返回他的值
}
}
return "";
},
deleteCookie: function(name){
this.setCookie(name, "", {expireDays:-1})
}
}
Cookie.setCookie("user","shi");
alert(Cookie.getCookie("user"));
Cookie.deleteCookie("user")
alert(Cookie.getCookie("user"));
</script>
<body>
<form id="form1" name="form1" method="post" action="">
<label>
<select name="select" οnchange="show(this);">
<option >请选择要查看的信息</option>
<option value="age">年龄</option>
<option value="name">姓名</option>
</select>
</label>
</form>
</body>
</html>