RSS

JAVASCRIPT – apply&call, caller&callee, Argument&arguments

03 May

这部分总结的比较零碎,包括以下内容:

ØArgument&arguments

Øapply&call

ØJSIEFirefox兼容性汇编

Øcaller&callee

ØArgument&arguments
Arguments
是进行函数调用时,除了指定的参数外,还另外创建的一个隐藏对象。Arguments是一个类似数组但不是数组的对象,说它类似数组是因为其具有数组一样的访问性质及方式,可以由arguments[n]来访问对应的单个参数的值,并拥有数组长度属性length。还有就是arguments对象存储的是实际传递给函数的参数,而不局限于函数声明所定义的参数列表,而且不能显式创建 arguments 对象。arguments 对象只有函数开始时才可用。下边例子详细说明了这些性质:
<script language=”JavaScript” type=”text/javascript”>
function ArgTest(a, b){
var i, s = “
测试内容:函数形参和函数实参
”;
var numargs = arguments.length;//
获取函数实参的数值。

var expargs = ArgTest.length;//
获取函数形参的数值。
s += “\n\n” + expargs + ”
个函数形参. “;
s += “\n” + numargs + ”
个函数实参
“;
s += “\n\n”
for (i =0 ; i < numargs; i++){//
获取参数内容。

s += i + ” = ” + arguments[i] + “\n”;
}
alert(s);//
返回参数列表。
}
Øapply&call
apply
call就是运行一个对象的方法, 只不过在运行的时候临时改变内部的this指向罢了。
apply:
方法名A.apply(对象名B, [执行A需要的参数,用数组表示]);
call:
方法名A.call(对象名B, [执行A需要的参数,用逗号分隔
]);
apply
call功能是: 执行某一个对象的方法A, 但在执行的时候临时把它内部的this指向一个别的对象B, 后面是执行A要用到的参数. applycall作用一样, 区别只不过是参数一个要用数组表示, 一个要用逗号分隔的方式表示. 看例子

function obj1(){
this.arg = 1;
this.M = function (a, b){
return this.arg + a + b;
}
}
function obj2(){
this.arg = 2;
}
var k1 = new obj1();
var k2 = new obj2();

上面定义了两个对象它们都有arg这个属性, 一个为1, 一个2, 当我们执行 k1.M(10, 20) , 得到31, 也就是说: k1.M(10, 20) == 31 //此时thisk1, arg1, 这句好理解再看语句: k1.M.apply(k2, [10, 20]) 这句意思是说: 执行k1对象的M方法, 但在执行的时候把该方法内部出现的this指向k2, 同时把10, 202个参数传给M. 由于k1.M在执行时,内部this指向了k2, k2arg属性值为2, 因此 this.arg + a + b = 2 + 10 + 20 = 32, 也就是说: k1.M.apply(k2, [10, 20]) == 32; //因为M内部this不再指向k1, 而指向k2 要用call方法, 只需要把后面参数换成用逗号分隔的就行, : k1.M.call(k2, 10, 20)
再看一个例子:
function obj(x){
this.arg = x;
this.M = function(){ return this.arg}
}
var a = new obj(1);

那么: a.M() a.M.apply(a) eval(“a.M()”) 完全是一个东西, 都是运行方法M 其中a.M.apply(a)的意思是:在运行的过程中, 临时把它内部this的指向改成a, 由于在这里它内部的this本来就是指向a, 因此实际上并没有改, 所以它和a.M()等价. 但如果有一个对象
:
var b = new obj(2);
a.M.apply(b);

那么这里的它不再等价a.M(), 因为a.M.apply(b)在运行的过程中把内部的this指向b,
a.M() == 1, a.M.apply(b) == 2
再看一个例子:

<input type=”text” id=”myText”  value=”input text”>
<script>
function Obj(){
this.value=”
对象!”;
}
var value=”global
变量
”;
function Fun1(){
alert(this.value);
}
window.Fun1();
Fun1.apply(window);
Fun1.apply(document.getElementById(‘myText’));
Fun1.apply(new Obj());
</script>
ØCaller&Callee
caller  
返回一个对函数的引用,该函数调用了当前函数。

functionName.caller functionName
对象是所执行函数的名称。
说明:对于函数来说,caller 属性只有在函数执行时才有定义。如果函数是由顶层调用的,那么 caller 包含的就是 null 。如果在字符串上下文中使用 caller属性,那么结果和 functionName.toString 一样,也就是说,显示的是函数的反编译文本。下面的例子说明了 caller 属性的用法:
function callerDemo() {
//
顶层函数调用,返回null
//
如果在字符串上下文中使用 caller属性,那么结果和 functionName.toString 一样

if (callerDemo.caller) {
//
如果再别的函数里调用,将打出这个function的源码
var a= callerDemo.caller.toString();
alert(a);
} else {
//
如果单独执行这个函数,就执行这段代码

alert(“this is a top function”);
}
}
function handleCaller() {
//
非顶层函数调用

callerDemo();
}

callee   返回正被执行的 Function 对象,也就是所指定的 Function 对象的正文。
[function.]arguments.callee
可选项 function 参数是当前正在执行的 Function 对象的名称。
说明 callee 属性的初始值就是正被执行的 Function 对象。 callee 属性是 arguments 对象的一个成员,它表示对函数对象本身的引用,这有利于匿名函数的递归或者保证函数的封装性,例如下边示例的递归计算1n的自然数之和。而该属性仅当相关函数正在执行时才可用。还有需要注意的是callee拥有length属性,这个属性有时候用于验证还是比较好的。arguments.length是实参长度,arguments.callee.length是形参长度,由此可以判断调用时形参长度是否和实参长度一致。示例 :
//callee
可以打印其本身

function calleeDemo() {
alert(arguments.callee);
}
//
用于验证参数
function calleeLengthDemo(arg1, arg2) {
if (arguments.length==arguments.callee.length) {
window.alert(“
验证形参和实参长度正确!”);
return;
} else {
alert(“
实参长度:
” +arguments.length);
alert(“
形参长度:
” +arguments.callee.length);
}
}
//
递归计算

var sum = function(n){
if (n <= 0)
return 1;
else
return n

arguments.callee(n – 1)
}

比较一般的递归函数:
var sum = function(n){
if (1==n) return 1;
else return n + sum (n-1);

调用时:alert(sum(100));
ØJS
IEFirefox(FF)兼容性汇编

1. document.form.item
问题
(1)
现有问题:
现有代码中存在许多 document.formName.item(“itemName”) 这样的语句,不能在 MF 下运行

(2)
解决方法:
改用
document.formName.elements[“elementName”]
EXAMPLE:
<script>
window.onload = function(){
if(document.all){
/*IE
还可以,它支持item,elements方法,它们可以通过名称访问,也可以通过下标来访问。item()方法在IE中只能使用()来取值,可以通过名称,可以通过数字下标,而elements可以通过[]或者()来访问
*/
alert(document.formname.item(“textform”).value);
//
这行代码不能实现
alert(document.formname.item[“textform”].value);
alert(document.formname.item(0).value);
//
这行代码不能实现
alert(document.formname.item[0].value);
alert(document.formname.elements[“textform”].value);
alert(document.formname.elements(“textform”).value);
alert(document.formname.elements(0).value);
alert(document.formname.elements[0].value);
}else{
//FF
只支持elements方法

alert(document.formname.elements[“textform”].value);
alert(document.formname.elements[0].value);
}
};
</script>
<form name=”formname”>
<input name=”textform” size=”10″ value=”TESTFORM”>
</form>
2.
集合类对象问题
(1)
现有问题:
现有代码中许多集合类对象取用时使用 ()IE 能接受,FF 不能。

(2)
解决方法:
改用 [] 作为下标运算。如:document.forms(“formName”) 改为 document.forms[“formName”]

又如:document.getElementsByName(“inputName”)(1) 改为 document.getElementsByName(“inputName”)[1]
3. window.event
(1)
现有问题
:
使用 window.event 无法在 FF 上运行

(2)
解决方法:
MF
event 只能在事件发生的现场使用,此问题暂无法解决。可以这样变通
:
<script>
function getMouse(e) {
e = e?e:(window.event?window.event:null);
if(document.all)
alert(e.target.id);
else
alet(e.srcElement.id);
}
</script>
<form name=”formname”>
<input type=”button” id=”FF” value=”
提交
” onclick=”getMouse(event)”/>
</form>
4. HTML
对象的 id 作为对象名的问题(注意是form的元素
)
(1)
现有问题

IE 中,HTML 对象的 ID(注意是form的元素)可以作为 document 的下属对象变量名直接使用。在 FF 中不能。
(2)
解决方法
getElementById(“idName”) 代替 idName 作为对象变量使用。
如果控件只有name,没有id, getElementById:IE:也可以找到对象FF:返回NULL
5.
idName字符串取得对象的问题(注意是form的元素)
(1)
现有问题

FF中,利用 eval(idName)(注意是form的元素) 可以取得 id idName HTML 对象,在IE 中不能。
(2)
解决方法
getElementById(idName) 代替 eval(idName)
6. event.x
event.y 问题
(1)
现有问题
IE 中,event 对象有 x, y 属性,FF中没有。
(2)
解决方法
FF中,与event.x 等效的是 event.pageX。但event.pageX IE中没有。
故采用 event.clientX 代替 event.x。在IE 中也有这个变量。
event.clientX
event.pageX 有微妙的差别(当整个页面有滚动条的时候),不过大多数时候是等效的。
如果要完全一样,可以稍麻烦些。
mX = event.x ? event.x : event.pageX;
然后用 mX 代替 event.x
7.
关于
frame
(1)
现有问题

IE可以用window.testFrame(idtestFrame)取得该framemf中不行
(2)
解决方法
frame的使用方面FFIE的最主要的区别是:
如果在frame标签中书写了以下属性
:
<frame src=”xx.htm” id=”frameId” name=”frameName” />

那么IE可以通过id或者name访问这个frame对应的window对象,而FF只可以通过name来访问这个frame对应的window对象。例如如果上述frame标签写在最上层的window里面的htm里面,那么可以这样访问

IE: window.top.frameId
或者window.top.frameName来访问这个window对象
FF:
只能这样window.top.frameName来访问这个window对象
另外,在FFIE中都可以使用window.top.document.getElementById(“frameId”)来访问frame标签,并且可以通过window.top.document.getElementById(“testFrame”).src = ‘xx.htm’来切换frame的内容,也都可以通过window.top.frameName.location = ‘xx.htm’来切换frame的内容。
8.
FF中,自己定义的属性必须getAttribute()取得
9.
FF中没有 parentElement parentElement.children 而用parentNode parentNode.childNodes
childNodes
的下标的含义在IEMF中不同,MF使用DOM规范,childNodes中会插入空白文本节点。

一般可以通过node.getElementsByTagName()来回避这个问题。html中节点缺失时,IEMFparentNode的解释不同,例如
<form>
<table>
<input/>
</table>
</form>
FF
input.parentNode的值为form, IEinput.parentNode的值为空节点,FF中节点没有removeNode方法,必须使用如下方法 node.parentNode.removeChild(node)
10.
元素属性

IE
input.type属性为只读,但是FF下可以修改
11.FF
不支持onpropertychange事件。
12.FF
不支持obj.insertAdjacentElement(“beforeBegin”,objText); 改为用obj.parentNode.insertBefore(objText,obj);
13.IE
支持innerTextFF支持
textContent
14.FF
对象名称中的$不能识别, 建议改为_。如:objName = “t1$spin”改为
objName = “t1_spin”
15.
事件名称和注册方式的变化:

IE:document.attachEvent(“onblur”, handler),detachEvent()/FF:document.addEventListener(“blur”, handler, false),removeEventListener
:为制定DOM对象事件类型注册多个事件处理函数的方法,它们有两个参数,第一个是事件类型,第二个是事件处理函数。在attachEvent()事件执行的时候,this关键字指向的是window对象,而不是发生事件的那个元素,通常的做法是用srcElement
16.FF
下用class代替IE下的className,由于class是关键字, 所以需要用 setAttribute/getAttribute才行,setAttribute(“class”,”css样式名称
”);

 

Advertisements
 
Leave a comment

Posted by on 05/03/2007 in JAVASCRIPT

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

 
%d bloggers like this: