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();      //global 变量
       Fun1.apply(window); //global 变量,相当于执行window.Fun1();(把Fun1函数应用在Window对象上,即Window.Fun1())
       Fun1.apply($('myText')); //input text,相当于执行 $('myText').Fun1();
       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').οnclick=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(){
    alert(this.name);
}
var obj=new Class();
//$('myChk').οnclick=obj.getName;
$('myChk').οnclick=obj.getName.bind(obj);
//$('myChk').οnclick=obj.getName.bind($('myChk'));
</script>

从上面代码可以看出bind/bindAsEventListener只是包装了一下apply/call方法,改变方法的调用对象。如例子,你可以把obj.getName方法转化成任何对象调用,并且把方法让表单元素触发。(bind和bindAsEventListener之间只是返回函数的参数不同)
这两个方法也可以用在对象之间的方法重用,实现类似继承方法的概念。看以下代码,其实是比较无聊的。

<script src="prototype1.3.1.js"></script>
<script>
function Class1(name){
    this.name=name;
}
Class1.prototype.getName=function(){
    alert(this.name);
}
function Class2(name){
    this.name=name;
  this.getName=Class1.prototype.getName.bind(this);
}
var obj1=new Class2("yql");
obj1.getName();
var obj2=new Object();
obj2.name="zkj";
obj2.fun=Class1.prototype.getName.bind(obj2);
obj2.fun();
</script>

我从来没读过prototype.js的扩展项目代码,也不知道bind..的最佳实践,一起挖掘吧。但你绝对不要把bind/bindAsEventListener从绑定的词义上来理解,可能会让你更加迷惑。从apply/call理解本质。应用某一对象的一个方法,用另一个对象替换当前对象。

5、关于事件的注册

<script src="prototype1.3.1.js"></script>
<input type=checkbox id=myChk name="chk" value=1> Test
<script>
Event.observe(myChk, 'click', showMessage, false);
//$('myChk').οnclick=showMessage;
//$('myChk').οnclick=showMessage.bind();
$('myChk').οnclick=showMessage.bind($('myChk'));
function showMessage() {
      alert(this.value);
}
</script>

执行上面代码,你就能明白Event.observe与bind/bindAsEventListener之间的区别:
(1) 显然Event.observe有限制,只能处理简单的函数,并函数中不能有this之类的东西。
(2)Event.observe内部用到addEventListener/attachEvent。能把多个函数加到一个触发事件(window.onload)。bind是覆盖。

6、关于事件监听最佳实践
很显然prototype.js提供的事件注册方法不是很完善。那看看dojo的时间注册吧(中文版),更加复杂,估计很多人像我一样,对于dojo暂时持观望态度。
如果你看过的前篇关于闭包的介绍,可能见过以下代码。
看以下代码前我想表述一个观点,任何网页中元素,浏览器都会为你创建一个对象(见)。(我觉得)这些对象与你建立javascript对象区别是它们有事件监听,会响应鼠标键盘的事件。如果你用了以下代码,那么把事件监听代码很好的转化到你的javascript代码中。

function associateObjWithEvent(obj, methodName){
    return (function(e){
        e = e||window.event;
        return obj[methodName](e, this);
    });
}
function DhtmlObject(elementId){
    var el = getElementWithId(elementId);
    if(el){
        el.onclick = associateObjWithEvent(this, "doOnClick");
        el.onmouseover = associateObjWithEvent(this, "doMouseOver");
        el.onmouseout = associateObjWithEvent(this, "doMouseOut");
    }
}
DhtmlObject.prototype.doOnClick = function(event, element){
    ... // doOnClick method body.
}
DhtmlObject.prototype.doMouseOver = function(event, element){
    ... // doMouseOver method body.
}
DhtmlObject.prototype.doMouseOut = function(event, element){
    ... // doMouseOut method body.
}

有时间我想用以上思想实现一个网页浮动框拖拉的代码(其实已经有很多了),待续........

prototype.js学习(1)相关推荐

  1. ajaxPro /prototype.js 学习笔记

    以下均为个人理解,如有不妥,请及时指正. 1.  定义和实现类之间的继承 A. 通过 直接引用和函数调用 function Child(name,age,sex) { this.name = name ...

  2. prototype.js教程及prototype中文手册

    在线API文档:   http://www.prototypejs.org/api 1.4网页版: http://thinhunan.cnblogs.com/archive/2006/04/01/De ...

  3. prototype使用学习手册指南之Position.js

    Position是prototype中定义的一个对象,提供了操作DOM中与位置相关的方法,要很好的理解元素在页面中的位置,具体代码如下,按照代码说说,其中英文是作者的注释,中文的才是偶的说明或翻译英文 ...

  4. prototype.js 1.4版开发者手册

    prototype.js是什么? 万一你没有使用过大名鼎鼎的prototype.js,那么让我来告诉你,prototype.js是由Sam Stephenson写的一个javascript类库.这个构 ...

  5. 转载:Prototype.js的中文使用手册

    转载自:http://thinhunan.cnblogs.com/archive/2006/04/01/DeveloperNotesForPrototype.html 转载仅为翻阅学习方便.感谢原文作 ...

  6. prototype.js开发笔记(转)

    prototype.js开发笔记 Table of Contents 1. Programming Guide 1.1. Prototype是什么? 1.2. 关联文章 1.3. 通用性方法 1.3. ...

  7. prototype.js开发者手册

    prototype.js开发者手册 对应版本1.4.0 original article by sp('Sergio Pereira') Sergio Pereira last update: Mar ...

  8. prototype.js详解

    prototype.js是什么? 万一你没有使用过大名鼎鼎的prototype.js,那么让我来告诉你,prototype.js是由Sam Stephenson写的一个javascript类库.这个构 ...

  9. JS学习笔记(九)深拷贝浅拷贝【Array、Object为例】

    JS学习笔记(九) 本系列更多文章,可以查看专栏 JS学习笔记 文章目录 JS学习笔记(九) 一.赋值&复制 二.浅拷贝(shallow copy) 1. 什么是浅拷贝 2. 数组的浅拷贝 ( ...

  10. 千锋Node.js学习笔记

    千锋Node.js学习笔记 文章目录 千锋Node.js学习笔记 写在前面 1. 认识Node.js 2. NVM 3. NPM 4. NRM 5. NPX 6. 模块/包与CommonJS 7. 常 ...

最新文章

  1. 使用多级分组报表展现分类数据
  2. python url配置单独放在某个应用目录中
  3. netflix 模式创新_创新设计模式:工厂模式
  4. Spring Boot通过@RequestParam接收前端表单传来的数据
  5. Linux: Apache 安全设定
  6. Java面试之JVM参数调优
  7. 传网易、京东6月相继赴港上市:共计筹资50亿美元
  8. 猜数游戏用Python应该这样写
  9. 【Spring Boot 实战】数据库千万级分库分表和读写分离实战
  10. 转行程序员深漂的这三年 #2
  11. Java学习笔记-Java概述和环境配置
  12. Linux常用指令指南
  13. 最新可使用在线音乐网站+多解析源码
  14. WebGIS开发培训(ArcGIS API for JavaScript方向)
  15. linux gmac驱动分析,以太网驱动流程浅析(一)-ifconfig主要流程
  16. 2022-2028年中国粮食物流行业市场发展调研及未来前景规划报告
  17. amCharts使用方式
  18. vue vue-quill-editor 富文本 改变图片大小
  19. html和linux下目录路径中 杠,点杠,点点杠区别
  20. 如何把标签输出为PDF文件

热门文章

  1. 【路径规划】基于matlab改进的粒子群算法路径规划【含Matlab源码 491期】
  2. 【单目标优化求解】基于matlab海洋捕食者算法(MPA)求解单目标问题【含Matlab源码 478期】
  3. 【跌倒检测】基于matlab中值滤波+二值化跌倒检测【含Matlab源码 344期】
  4. android自定义sufaceview,Android自定义SurfaceView实现画板功能
  5. 机器学习 结构化数据_聊天机器人:根据结构化数据创建自然语言
  6. 集群为什么最少6个_结构化面试答题技巧:多年的经验告诉你,最少要注意这6个方面...
  7. mysql数据库数据表的指令_mysql数据库和表操作命令
  8. 让一个.sh文件一直运行_想做AI鉴黄工具?这有一个内含20多万张“不可描述”图片的数据集...
  9. windows mysql 5.5 升级_windows环境mysql5.0晋级mysql5.5
  10. java面试jquery问题_20个最常见的jQuery面试问题及答案