JavaScript 是一种非常灵活的面向对象程序设计语言,它与传统的强类型的面向对象程序设计语言(如 C++,Java,C# 等)有很大不同,所以要实现如 C++、java、C# 当中的一些特性就需要换一种思考方式来解决。今天主要讨论如何在 JavaScript 脚本中实现数据的封装(encapsulation)。 数据封装说的简单点就是把不希望调用者看见的内容隐藏起来。它是面向对象程序设计的三要素之首,其它两个是继承和多态,关于它们的内容在后面再讨论。 关于数据封装的实现,在 C++、Java、C# 等语言中是通过 public、private、static 等关键字实现的。在 JavaScript 则采用了另外一种截然不同的形式。在讨论如何具体实现某种方式的数据封装前,我们先说几个简单的,大家所熟知却又容易忽略的 JavaScript 的概念。 1 几个基本概念 1.1 变量定义 在 JavaScript 语言中,是通过 var 关键字来定义变量的。 但是如果我们直接给一个没有使用 var 定义的变量赋值,那么这个变量就会成为全局变量。 一般情况下,我们应该避免使用没有用 var 定义的变量,主要原因是它会影响程序的执行效率,因为存取全局变量速度比局部变量要慢得多。 但是这种用法可以保证我们的变量一定是全局变量。 另外,为了保证速度,我们在使用全局变量时,可以通过 var 定义一个局部变量,然后将全局变量赋予之,由此可以得到一个全局变量的局部引用。 1.2 变量类型 没有定义的变量,类型为 undefined。 变量的值可以是函数。 函数在 JavaScript 中可以充当类的角色。 1.3 变量作用域 变量作用域是指变量生存周期的有效范围。 单纯用 { } 创建的块不能创建作用域。 with 将它包含的对象作用域添加到当前作用域链中,但 with 不创建新的作用域。with 块结束后,会将对象作用域从当前作用域链中删除。 try-catch 中,catch 的错误对象只在 catch 块中有效,但 catch 块中定义的变量属于当前作用域。 其它如 if、for、for-in、while、do-while、switch 等控制语句创建的块不能创建作用域。 用 function 创建的函数,会创建一个新的作用域添加到当前作用域中。 2 封装 下面我们就来讨论具体的封装。首先说一下大家最熟悉的几种封装:私有实例成员、公有实例成员和公有静态成员。最后会讨论一下大家所不熟悉的私有静态成员和静态类的封装办法。因为下面要讨论的是面向对象编程,所有当函数作为类来定义和使用时,我们暂且将其成为类。 2.1 私有实例成员 私有实例成员在 JavaScript 中实际上可以用函数内的局部变量来实现,它相当于类的私有实例成员。例如: class1 = function() { // private […]
View Details提起面向对象我们就能想到类,对象,封装,继承,多态。在《javaScript高级程序设计》(人民邮电出版社,曹力、张欣译。英文名字是:Professional JavaScript for Web Developers)这本书中描述的还算比较详细。我们看看JavaScript中定义类的各种方法。 1.工厂方式 javaScript中创建自己的类和对象,我们应该是必须掌握的,我们都知道javaScript中对象的属性可以在对象创建后动态定义,比如下面的代码: 复制代码代码如下: <script type="text/javascript"> //定义 var oCar = new Object(); oCar.color = "red"; oCar.doors = 4; oCar.showColor = function() { alert(this.color); } //调用 oCar.showColor(); </script> 我们很容易使用oCar对象,但是我们创就是想创建多个Car实例。我们可以使用一个函数来封装上面的代码来实现:<script type="text/javascript"> 复制代码代码如下: //定义 function createCar() { var oCar = new Object(); oCar.color = "red"; oCar.doors = 4; oCar.showColor = function() { alert(this.color); } return oCar; } //调用 var ocar1 = createCar(); var ocar2 = createCar(); ocar1.color = "black"; ocar1.showColor(); ocar2.showColor(); </script> 顺便说一下,javaScript对象默认成员属性都是public 的。这种方式我们称为工厂方式,我们创造了能创建并返回特定类型的对象的工厂。 这样做有点意思了,但是在面向对象中我们经常使用创建对象的方法是: Car car=new Car(); 使用new 关键字已经深入人心,因此我们使用上面的方法去定义总感觉别扭,并且每次调用时都去创建新的属性以及函数,功能上也不实际。下来我们看看构造函数的形式定义类。 2.构造函数 这种方式看起来有点象工厂函数。具体表现如下: 复制代码代码如下: <script type="text/javascript"> //定义 function Car(color, doors) { this.color = color; this.doors = doors; this.showColor = function() { alert(this.color); }; } //调用 var car1 = new Car("red", 4); var car2 = new Car("blue", 4); car1.showColor(); car2.showColor(); </script> 看起来效果很明显,有差别了吧。感觉有点意思了。在构造函数内部创造对象使用this 关键字,使用new 运算符创建对象感觉非常亲切。但是也有点问题:每次new 对象时都会创建所有的属性,包括函数的创建,也就是说多个对象完全独立,我们定义类的目的就是为了共享方法以及数据,但是car1对象与car2对象都是各自独立的属性与函数,最起码我们应该共享方法。这就是原形方式的优势所在。 3.原型方式 利用对象的prototype属性,可把它看出创建新对象所依赖的原型。方法如下: 复制代码代码如下: <script type="text/javascript"> //定义 function Car() { }; Car.prototype.color = "red"; Car.prototype.doors = 4; Car.prototype.drivers = new […]
View Details这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现"继承"。 今天是最后一个部分,介绍不使用构造函数实现"继承"。 一、什么是"非构造函数"的继承? 比如,现在有一个对象,叫做"中国人"。 var Chinese = {nation:’中国'}; 还有一个对象,叫做"医生"。 var Doctor ={career:’医生'} 请问怎样才能让"医生"去继承"中国人",也就是说,我怎样才能生成一个"中国医生"的对象? 这里要注意,这两个对象都是普通对象,不是构造函数,无法使用构造函数方法实现"继承"。 二、object()方法 json格式的发明人Douglas Crockford,提出了一个object()函数,可以做到这一点。 function object(o) { function F() {} F.prototype = o; return new F(); } 这个object()函数,其实只做一件事,就是把子对象的prototype属性,指向父对象,从而使得子对象与父对象连在一起。 使用的时候,第一步先在父对象的基础上,生成子对象: var Doctor = object(Chinese); 然后,再加上子对象本身的属性: Doctor.career = '医生'; 这时,子对象已经继承了父对象的属性了。 alert(Doctor.nation); //中国 三、浅拷贝 除了使用"prototype链"以外,还有另一种思路:把父对象的属性,全部拷贝给子对象,也能实现继承。 下面这个函数,就是在做拷贝: function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i];} c.uber = p; return c;} 使用的时候,这样写: var Doctor = extendCopy(Chinese); Doctor.career = '医生'; alert(Doctor.nation); // 中国 但是,这样的拷贝有一个问题。那就是,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。 请看,现在给Chinese添加一个"出生地"属性,它的值是一个数组。 Chinese.birthPlaces = ['北京',’上海',’香港']; 通过extendCopy()函数,Doctor继承了Chinese。 var Doctor = extendCopy(Chinese); 然后,我们为Doctor的"出生地"添加一个城市: […]
View Details这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例。 今天要介绍的是,如何生成一个"继承"多个对象的实例。 比如,现在有一个"动物"对象的构造函数, function Animal(){ this.species = "动物"; } 还有一个"猫"对象的构造函数, function Cat(name,color){ this.name = name; this.color = color; } 怎样才能使"猫"继承"动物"呢? 1. 构造函数绑定 最简单的方法,大概就是使用call或apply方法,将父对象的构造函数绑定在子对象上,也就是在子对象构造函数中加一行: function Cat(name,color){ Animal.apply(this, arguments); this.name = name; this.color = color; } var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物 2. prototype模式 更常见的做法,则是使用prototype属性。 如果"猫"的prototype对象,指向一个Animal的实例,那么所有"猫"的实例,就能继承Animal了。 Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物 代码的第一行,我们将Cat的prototype对象指向一个Animal的实例。 Cat.prototype = new Animal(); 它相当于完全删除了prototype 对象原先的值,然后赋予一个新值。但是,第二行又是什么意思呢? Cat.prototype.constructor = Cat; 原来,任何一个prototype对象都有一个constructor属性,指向它的构造函数。也就是说,Cat.prototype 这个对象的constructor属性,是指向Cat的。 我们在前一步已经删除了这个prototype对象原来的值,所以新的prototype对象没有constructor属性,所以我们必须手动加上去,否则后面的"继承链"会出问题。这就是第二行的意思。 总之,这是很重要的一点,编程时务必要遵守。下文都遵循这一点,即如果替换了prototype对象, o.prototype = {}; 那么,下一步必然是为新的prototype对象加上constructor属性,并将这个属性指回原来的构造函数。 o.prototype.constructor = o; 3. 直接继承prototype 由于Animal对象中,不变的属性都可以直接写入Animal.prototype。所以,我们也可以让Cat()跳过 Animal(),直接继承Animal.prototype。 现在,我们先将Animal对象改写: function […]
View Details学习Javascript,最难的地方是什么? 我觉得,Object(对象)最难。因为Javascript的Object模型很独特,和其他语言都不一样,初学者不容易掌握。 下面就是我的学习笔记,希望对大家学习这个部分有所帮助。我主要参考了以下两本书籍: 《面向对象的Javascript》(Object-Oriented JavaScript) 《Javascript高级程序设计(第二版)》(Professional JavaScript for Web Developers, 2nd Edition) 它们都是非常优秀的Javascript读物,推荐阅读。 笔记分成三部分。今天的第一部分是讨论"封装"(Encapsulation),后面的第二部分和第三部分讨论"继承"(Inheritance)。 ============================ Javascript 面向对象编程(一):封装 作者:阮一峰 Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象。但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类)。 那么,如果我们要把"属性"(property)和"方法"(method),封装成一个对象,甚至要从原型对象生成一个实例对象,我们应该怎么做呢? 1. 生成对象的原始模式 假定我们把猫看成一个对象,它有"名字"和"颜色"两个属性。 var Cat = { name : ", color : " } 现在,我们需要根据这个原型对象,生成两个实例对象。 var cat1 = {}; // 创建一个空对象 cat1.name = "大毛"; // 按照原型对象的属性赋值 cat1.color = "黄色"; var cat2 = {}; cat2.name = "二毛"; cat2.color = "黑色"; 好了,这就是最简单的封装了。但是,这样的写法有两个缺点,一是如果多生成几个实例,写起来就非常麻烦;二是实例与原型之间,没有任何办法,可以看出有什么联系。 2. 原始模式的改进 我们可以写一个函数,解决代码重复的问题。 function Cat(name,color){ return { name:name, color:color } } 然后生成实例对象,就等于是在调用函数: var cat1 = Cat("大毛","黄色"); var cat2 = Cat("二毛","黑色"); 这种方法的问题依然是,cat1和cat2之间没有内在的联系,不能反映出它们是同一个原型对象的实例。 3. 构造函数模式 为了解决从原型对象生成实例的问题,Javascript提供了一个构造函数(Constructor)模式。 所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量。对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例对象上。 比如,猫的原型对象现在可以这样写, function Cat(name,color){ […]
View DetailsMath 对象 Math 对象用于执行数学任务。 使用 Math 的属性和方法的语法:
1 |
var pi_value=Math.PI;var sqrt_value=Math.sqrt(15); |
注释:Math 对象并不像 Date 和 String 那样是对象的类,因此没有构造函数 Math(),像 Math.sin() 这样的函数只是函数,不是某个对象的方法。您无需创建它,通过把 Math 作为对象使用就可以调用其所有属性和方法。 Math 对象属性 FF: Firefox, IE: Internet Explorer 属性 描述 FF IE E 返回算术常量 e,即自然对数的底数(约等于2.718)。 1 3 LN2 返回 2 的自然对数(约等于0.693)。 1 3 LN10 返回 10 的自然对数(约等于2.302)。 1 3 LOG2E 返回以 2 为底的 e 的对数(约等于 1.414)。 1 3 LOG10E 返回以 10 为底的 e 的对数(约等于0.434)。 1 3 PI 返回圆周率(约等于3.14159)。 1 3 SQRT1_2 返回返回 2 的平方根的倒数(约等于 0.707)。 1 3 SQRT2 返回 2 的平方根(约等于 1.414)。 1 3 Math 对象方法 FF: Firefox, IE: Internet […]
View Details以下以 ie 代替 internet explorer,以 mf 代替 mozzila firefox 1. document.form.item 问题(1)现有问题:现有代码中存在许多 document.formname.item("itemname") 这样的语句,不能在 mf 下运行(2)解决方法:改用 document.formname.elements["elementname"](3)其它参见 2 2. 集合类对象问题(1)现有问题:现有代码中许多集合类对象取用时使用 (),ie 能接受,mf 不能。(2)解决方法:改用 [] 作为下标运算。如:document.forms("formname") 改为 document.forms["formname"]。又如:document.getelementsbyname("inputname")(1) 改为 document.getelementsbyname("inputname")[1](3)其它 3. window.event(1)现有问题:使用 window.event 无法在 mf 上运行(2)解决方法:mf 的 event 只能在事件发生的现场使用,此问题暂无法解决。可以这样变通:原代码(可在ie中运行):<input type="button" name="somebutton" value="提交" onclick="javascript:gotosubmit()"/>…<script language="javascript">function gotosubmit() {…alert(window.event); // use window.event…}</script> 新代码(可在ie和mf中运行):<input type="button" name="somebutton" value="提交" onclick="javascript:gotosubmit(event)"/>…<script language="javascript">function gotosubmit(evt) {evt = evt ? evt : (window.event ? window.event : null);…alert(evt); // use evt…}</script>此外,如果新代码中第一行不改,与老代码一样的话(即 gotosubmit 调用没有给参数),则仍然只能在ie中运行,但不会出错。所以,这种方案 tpl 部分仍与老代码兼容。 4. html 对象的 id 作为对象名的问题(1)现有问题在 ie 中,html 对象的 id 可以作为 document 的下属对象变量名直接使用。在 mf 中不能。(2)解决方法用 getelementbyid("idname") […]
View Details<!--if(window.Event){// 修正Event的DOM /* IE5 MacIE5 Mozilla Konqueror2.2 Opera5 event yes yes yes yes yes event.returnValue yes yes no no no event.cancelBubble yes yes no no no event.srcElement yes yes no no no event.fromElement yes yes no no no */ Event.prototype.__defineSetter__("returnValue",function(b){// if(!b)this.preventDefault(); return b; }); Event.prototype.__defineSetter__("cancelBubble",function(b){// 设置或者检索当前事件句柄的层次冒泡 if(b)this.stopPropagation(); return b; }); Event.prototype.__defineGetter__("srcElement",function(){ var node=this.target; while(node.nodeType!=1)node=node.parentNode; return node; }); Event.prototype.__defineGetter__("fromElement",function(){// 返回鼠标移出的源节点 var node; if(this.type=="mouseover") node=this.relatedTarget; else if(this.type=="mouseout") node=this.target; if(!node)return; while(node.nodeType!=1)node=node.parentNode; return node; }); Event.prototype.__defineGetter__("toElement",function(){// 返回鼠标移入的源节点 var node; if(this.type=="mouseout") node=this.relatedTarget; else if(this.type=="mouseover") node=this.target; if(!node)return; while(node.nodeType!=1)node=node.parentNode; return node; }); Event.prototype.__defineGetter__("offsetX",function(){ return this.layerX; }); Event.prototype.__defineGetter__("offsetY",function(){ return this.layerY; }); }if(window.Document){// 修正Document的DOM /* IE5 MacIE5 Mozilla Konqueror2.2 Opera5 document.documentElement yes yes yes yes no document.activeElement yes null no no no */ }if(window.Node){// 修正Node的DOM /* IE5 MacIE5 Mozilla Konqueror2.2 Opera5 Node.contains yes yes no no yes Node.replaceNode yes no no no no Node.removeNode yes no no no no Node.children yes yes no no no Node.hasChildNodes yes yes yes yes no Node.childNodes yes yes yes yes no Node.swapNode yes no no no no Node.currentStyle yes yes no no no */ Node.prototype.replaceNode=function(Node){// 替换指定节点 this.parentNode.replaceChild(Node,this); } Node.prototype.removeNode=function(removeChildren){// 删除指定节点 if(removeChildren) return this.parentNode.removeChild(this); else{ var range=document.createRange(); range.selectNodeContents(this); return this.parentNode.replaceChild(range.extractContents(),this); } } Node.prototype.swapNode=function(Node){// 交换节点 var nextSibling=this.nextSibling; var parentNode=this.parentNode; node.parentNode.replaceChild(this,Node); parentNode.insertBefore(node,nextSibling); } }if(window.HTMLElement){ HTMLElement.prototype.__defineGetter__("all",function(){ var a=this.getElementsByTagName("*"); var node=this; a.tags=function(sTagName){ return node.getElementsByTagName(sTagName); } return a; }); HTMLElement.prototype.__defineGetter__("parentElement",function(){ if(this.parentNode==this.ownerDocument)return null; return this.parentNode; }); HTMLElement.prototype.__defineGetter__("children",function(){ var tmp=[]; var j=0; var n; for(var i=0;i<this.childNodes.length;i++){ n=this.childNodes[i]; if(n.nodeType==1){ tmp[j++]=n; if(n.name){ if(!tmp[n.name]) tmp[n.name]=[]; tmp[n.name][tmp[n.name].length]=n; } if(n.id) tmp[n.id]=n; } } return tmp; }); HTMLElement.prototype.__defineGetter__("currentStyle", function(){ return this.ownerDocument.defaultView.getComputedStyle(this,null); }); HTMLElement.prototype.__defineSetter__("outerHTML",function(sHTML){ var r=this.ownerDocument.createRange(); r.setStartBefore(this); var df=r.createContextualFragment(sHTML); this.parentNode.replaceChild(df,this); return sHTML; }); HTMLElement.prototype.__defineGetter__("outerHTML",function(){ var attr; var attrs=this.attributes; var str="<"+this.tagName; for(var i=0;i<attrs.length;i++){ attr=attrs[i]; if(attr.specified) str+=" "+attr.name+'="'+attr.value+'"'; } if(!this.canHaveChildren) return str+">"; return str+">"+this.innerHTML+"</"+this.tagName+">"; }); HTMLElement.prototype.__defineGetter__("canHaveChildren",function(){ switch(this.tagName.toLowerCase()){ case "area": case "base": case "basefont": case "col": case "frame": case "hr": case "img": case "br": case "input": case "isindex": case "link": case "meta": case "param": return false; } return true; }); HTMLElement.prototype.__defineSetter__("innerText",function(sText){ var parsedText=document.createTextNode(sText); this.innerHTML=parsedText; return parsedText; }); HTMLElement.prototype.__defineGetter__("innerText",function(){ var r=this.ownerDocument.createRange(); r.selectNodeContents(this); return r.toString(); }); HTMLElement.prototype.__defineSetter__("outerText",function(sText){ var parsedText=document.createTextNode(sText); this.outerHTML=parsedText; return parsedText; }); HTMLElement.prototype.__defineGetter__("outerText",function(){ var r=this.ownerDocument.createRange(); r.selectNodeContents(this); return r.toString(); }); HTMLElement.prototype.attachEvent=function(sType,fHandler){ var shortTypeName=sType.replace(/on/,""); fHandler._ieEmuEventHandler=function(e){ window.event=e; return fHandler(); } this.addEventListener(shortTypeName,fHandler._ieEmuEventHandler,false); } HTMLElement.prototype.detachEvent=function(sType,fHandler){ var shortTypeName=sType.replace(/on/,""); if(typeof(fHandler._ieEmuEventHandler)=="function") this.removeEventListener(shortTypeName,fHandler._ieEmuEventHandler,false); else this.removeEventListener(shortTypeName,fHandler,true); } HTMLElement.prototype.contains=function(Node){// 是否包含某节点 do if(Node==this)return true; while(Node=Node.parentNode); return false; } HTMLElement.prototype.insertAdjacentElement=function(where,parsedNode){ switch(where){ case "beforeBegin": this.parentNode.insertBefore(parsedNode,this); break; case "afterBegin": this.insertBefore(parsedNode,this.firstChild); break; case "beforeEnd": this.appendChild(parsedNode); break; case "afterEnd": if(this.nextSibling) this.parentNode.insertBefore(parsedNode,this.nextSibling); else this.parentNode.appendChild(parsedNode); break; } } HTMLElement.prototype.insertAdjacentHTML=function(where,htmlStr){ var r=this.ownerDocument.createRange(); r.setStartBefore(this); var parsedHTML=r.createContextualFragment(htmlStr); this.insertAdjacentElement(where,parsedHTML); } HTMLElement.prototype.insertAdjacentText=function(where,txtStr){ var parsedText=document.createTextNode(txtStr); this.insertAdjacentElement(where,parsedText); } HTMLElement.prototype.attachEvent=function(sType,fHandler){ var shortTypeName=sType.replace(/on/,""); fHandler._ieEmuEventHandler=function(e){ window.event=e; return fHandler(); } this.addEventListener(shortTypeName,fHandler._ieEmuEventHandler,false); } HTMLElement.prototype.detachEvent=function(sType,fHandler){ var shortTypeName=sType.replace(/on/,""); if(typeof(fHandler._ieEmuEventHandler)=="function") this.removeEventListener(shortTypeName,fHandler._ieEmuEventHandler,false); else this.removeEventListener(shortTypeName,fHandler,true); } }//--></script>?>
View Details在FireFox下编写事件处理函数是很麻烦的事. 因为FireFox并没有 window.event . 如果要得到 event 对象,就必须要声明时间处理函数的第一个参数为event. 所以为了兼容IE与FireFox,一般的事件处理方法为:btn.onclick=handle_btn_click;function handle_btn_click(evt){ if(evt==null)evt=window.event;//IE //处理事件.}对于简单的程序,这不算麻烦. 但对于一些复杂的程序,某写函数根本就不是直接与事件挂钩的.如果要把event传进该参数,那么所有的方法都要把event传来传去..这简直就是噩梦. 下面介绍一个解决这个麻烦事的方法,与原理. JScript中,函数的调用是有一个 func.caller 这个属性的.例如 function A(){ B();}function B(){ alert(B.caller);}如果B被A调用,那么B.caller就是A 另外,函数有一个arguments属性. 这个属性可以遍历函数当前执行的参数:function myalert(){ var arr=[]; for(var i=0;i arr[i]=myalert.arguments[i]; alert(arr.join("-"));}alert("hello","world",1,2,3)就能显示 hello-world-1-2-3(arguments的个数与调用方有关,而与函数的参数定义没有任何关系) 根据这两个属性,我们可以得到第一个函数的event对象:btn.onclick=handle_click;function handle_click(){ showcontent();}function showcontent(){ var evt=SearchEvent(); if(evt&&evt.shiftKey)//如果是基于事件的调用,并且shift被按下 window.open(global_helpurl); else location.href=global_helpurl;}function SearchEvent(){ func=SearchEvent.caller; while(func!=null) { var arg0=func.arguments[0]; if(arg0) { if(arg0.constructor==Event) // 如果就是event 对象 return arg0; } func=func.caller; } return null;}这个例子使用了SearchEvent来搜索event对象. 其中 'Event' 是 FireFox 的 event.constructor .在该例子运行时,SearchEvent.caller就是showcontent,但是showcontent.arguments[0]是空.所以 func=func.caller 时,func变为handle_click .handle_click 被 FireFox 调用, 虽然没有定义参数,但是被调用时,第一个参数就是event,所以handle_click.arguments[0]就是event ! 针对上面的知识,我们可以结合 prototype.__defineGetter__ 来实现 window.event 在 FireFox 下的实现: 下面给出一个简单的代码.. 有兴趣的可以补充 if(window.addEventListener){ FixPrototypeForGecko();}function FixPrototypeForGecko(){ HTMLElement.prototype.__defineGetter__("runtimeStyle",element_prototype_get_runtimeStyle); window.constructor.prototype.__defineGetter__("event",window_prototype_get_event); Event.prototype.__defineGetter__("srcElement",event_prototype_get_srcElement);}function element_prototype_get_runtimeStyle(){ //return style instead… return […]
View Details1、event代表事件的状态,例如触发event对象的元素、鼠标的位置及状态、按下的键等等。event对象只在事件发生的过程中才有效。event的某些属性只对特定的事件有意义。比如,fromElement 和 toElement 属性只对 onmouseover 和 onmouseout 事件有意义。 2、属性: altKey, button, cancelBubble, clientX, clientY, ctrlKey, fromElement, keyCode, offsetX, offsetY, propertyName, returnValue, screenX, screenY, shiftKey, srcElement, srcFilter, toElement, type, x, y 3、属性详细说明: 属性名 描述 值 说明 altKey 检查alt键的状态 当alt键按下时,值为True否则为False 只读 shiftKey 检查shift键的状态 当shift键按下时,值为True否则为False 只读 ctrlKey 检查ctrl键的状态 当ctrl键按下时,值为True否则为False 只读 例:(点击按钮时显示那几个特殊键按下的状态) <input type="button" value="点击" onClick="showState()"/> <script> function show(){ alert("altKey:"+window.event.altKey +"\nshiftKey:"+window.event.shiftKey +"\nctrlKey:"+window.event.ctrlKey); }</script> keyCode 检测键盘事件相对应的内码 可读写,可以是任何一个Unicode键盘内码。如果没有引发键盘事件,则该值为0 例:(按回车键让下一组件得到焦点,相当按Tab键) <input type="text" onKeyDown="nextBlur()"/> <input type="text"/> <script> function nextBlur(){ if(window.event.keyCode==13)//回车键的 code window.event.keyCode=9;//Tab键的code } </script> srcElement 返回触发事件的元素 Object 只读 例:(点击按钮时显示按钮的name值) <input type="button" value="闽" name="福建" onClick="show()"/> […]
View Details