日期:2014-05-16  浏览次数:20295 次

关于javascript的apply和call函数

1、关于javascript的apply和call函数

prototype.js中用了大量的apply和call函数,不注意会造成理解偏差。
官方解释:应用某一对象的一个方法,用另一个对象替换当前对象。
apply与call的区别是第二个参数不同。apply是? 数组或者arguments 对象。而call是逗号隔开的任何类型。

apply,call方法最让人混淆的地方也是apply,call的特色。但最好不要滥用。
能改变调用函数的对象。如下例,函数中用到this关键字,这时候this代表的是apply,call函数的第一个参数。

<script src="prototype1.3.1.js"></script>
<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($('myText'));?
?? Fun1.apply(new Obj());?
</script>

2、关于闭包?
prototype.js在Class.create,bind等中用到javascript的闭包特色。但整体上prototype.js对于强大的闭包特性用的不多。大家可以参阅我翻译的篇文章了解闭包。
3、让我比较反感的两个方法
(1)
var Class = {
? create: function() {
??? return function() {?
????? this.initialize.apply(this, arguments);
??? }
? }
}
很讨厌用别的语言的风格来写javascript。用这个方法构造自定义类? 并没有觉得有多方便,减少代码行数,只会让人难理解,多定义一个initialize方法。
其实讨厌这条有些牵强,不过修改Object的原型对象就有点过分了。
(2)Object.prototype.extend
? 先不过你取个extend的名字会让熟悉java的人引起的歧义。修改Object的prototype就说不过去了。不知道作者是怎么考虑的。当你for in循环对象是,麻烦就来了。可能有人会问你for in干吗。 我一个项目中既用了DWR,也用了prototype.js,dwr返回的javascript对象都多了个exetend属性,还得特殊处理。
? 以前我比较过dojo和prototype.js中继承的实现,现在我明白个道理。对于javascript这种没有静态类型检查,语法宽松的语言来讲,如果你选择了某个js类库,那你也必须适应作者写javascript的风格。prototype.js的作者对extend的使用炉火纯青,如果我们不当它只是个属性拷贝的函数的话,多读读prototype.js的代码是好的。
4、关于函数的绑定
? 类库提供了Function.prototype.bind? Function.prototype.bindAsEventListener两个方法。首先我们从概念上解释一个这两个方法。
任何一个函数都可以调用这两个方法;参数的是javascript对象或网页上元素对象;返回类型是个函数对象。
本来我就是个函数,返回还是函数,到这两个函数有什么不同呢。看实现代码,关键还是apply\call函数的代码。其实这里只是转化了一下方法调用的对象。

<script src="prototype1.3.1.js"></script>
<input type=checkbox id=myChk name="asf" value=1> Test
<script>
??? var CheckboxWatcher = Class.create();
??? CheckboxWatcher.prototype = {
?????? initialize: function(chkBox, message) {
??????????? this.chkBox = $(chkBox);
??????????? this.message = message;
??????????? this.chkBox.onclick = this.showMessage.bindAsEventListener(this);
?????? },
?????? showMessage: function(evt) {
????????? alert(this.message + ' (' + evt.type + ')');
?????? }
??? };
new CheckboxWatcher('myChk','message!!!!');
//$('myChk').onclick=function(){};
</script>
这是?https://compdoc2cn.dev.java.net/?上举的例子,个人感觉没什么意思,反而让我对bind,bindAsEventListener有些反感。(javascript就是这样,明明大家都知道的语法,但写出来的代码差别确很大)
看下面代码:

<script src="prototype1.3.1.js"></script>
<input type=checkbox id=myChk name="chk" value=1> Test
<script>
function Class(){
??? this.name="class";
}
Class.prototype.getName=function(){
??? al