javascript 中对象的继承〔转贴〕


Posted in Javascript onJanuary 22, 2007

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(){
    alert(this.name);
}
var obj=new Class();
//$('myChk').onclick=obj.getName;
$('myChk').onclick=obj.getName.bind(obj);
//$('myChk').onclick=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').onclick=showMessage;
//$('myChk').onclick=showMessage.bind();
$('myChk').onclick=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.
}

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

Javascript 相关文章推荐
JavaScript中的Math.LOG2E属性使用详解
Jun 14 Javascript
jquery实现表格中点击相应行变色功能效果【实例代码】
May 09 Javascript
jQuery多文件异步上传带进度条实例代码
Aug 16 Javascript
JS键盘版计算器的制作方法
Dec 03 Javascript
利用JS判断鼠标移入元素的方向
Dec 11 Javascript
从零开始学习Node.js系列教程四:多页面实现的数学运算示例
Apr 13 Javascript
angular2中Http请求原理与用法详解
Jan 11 Javascript
JS判断用户用的哪个浏览器实例详解
Oct 09 Javascript
Intellij IDEA搭建vue-cli项目的方法步骤
Oct 20 Javascript
原生js实现五子棋游戏
May 28 Javascript
解决vue 退出动画无效的问题
Aug 09 Javascript
angular *Ngif else用法详解
Dec 15 Javascript
利用javascript中的call实现继承
Jan 22 #Javascript
Javascript里使用Dom操作Xml
Jan 22 #Javascript
幻宇的层模拟窗口效果-提供演示和下载
Jan 20 #Javascript
写的htc的数据表格
Jan 20 #Javascript
共享自己写一个框架DreamScript
Jan 20 #Javascript
javascript读取RSS数据
Jan 20 #Javascript
一个多次搜索+多次传值的解决方案
Jan 20 #Javascript
You might like
十天学会php之第四天
2006/10/09 PHP
PHP 文件类型判断代码
2009/03/13 PHP
php下统计用户在线时间的一种尝试
2010/08/26 PHP
wamp下修改mysql访问密码的解决方法
2013/05/07 PHP
yii框架结合charjs实现统计30天数据的方法
2020/04/04 PHP
jQuery中DOM操作实例分析
2015/01/23 Javascript
jQuery实现带延迟效果的滑动菜单代码
2015/09/02 Javascript
JS代码实现根据时间变换页面背景效果
2016/06/16 Javascript
js实现楼层导航功能
2017/02/23 Javascript
JS分页的实现(同步与异步)
2017/09/16 Javascript
js 取消页面可以选中文字的功能方法
2018/01/02 Javascript
vue项目国际化vue-i18n的安装使用教程
2018/03/14 Javascript
微信小程序通过一个json实现分享朋友圈图片
2019/09/03 Javascript
[00:36]DOTA2上海特级锦标赛 Archon战队宣传片
2016/03/04 DOTA
[00:52]黑暗之门更新 新英雄孽主驾临DOTA2
2016/08/24 DOTA
python 图片验证码代码
2008/12/07 Python
Python原始字符串与Unicode字符串操作符用法实例分析
2017/07/22 Python
python调用百度语音识别实现大音频文件语音识别功能
2018/08/30 Python
Python GUI编程学习笔记之tkinter控件的介绍及基本使用方法详解
2020/03/30 Python
Python基于BeautifulSoup爬取京东商品信息
2020/06/01 Python
Python turtle库的画笔控制说明
2020/06/28 Python
Python模拟登录requests.Session应用详解
2020/11/17 Python
HTML5 3D衣服摇摆动画特效
2016/03/17 HTML / CSS
Under Armour安德玛法国官网:美国高端运动科技品牌
2018/06/29 全球购物
iHerb中文官网:维生素、保健品和健康产品
2018/11/01 全球购物
SHEIN台湾:购买最新流行女装服饰
2019/05/18 全球购物
销售副总经理岗位职责
2013/12/11 职场文书
电子商务网站的创业计划书
2014/01/05 职场文书
女方回门宴答谢词
2014/01/14 职场文书
活动总结结尾怎么写
2014/08/30 职场文书
祖国在我心中演讲稿600字
2014/09/23 职场文书
护士心得体会范文
2016/01/25 职场文书
JavaWeb实现显示mysql数据库数据
2022/03/19 Java/Android
CSS SandBox应用场景及常见问题
2022/06/25 HTML / CSS
新的CSS 伪类函数 :is() 和 :where()示例详解
2022/08/05 HTML / CSS
VW、VH适配移动端的解决方案与常见问题
2023/05/21 HTML / CSS