04月
12日

jQuery的实践应用

类归于: 做东西 Hbomb 写于 06:22

最近在做一个叫“商业大亨”的网页游戏,已接近尾声了,游戏主界面是采用flash里表现的,主要基于flash丰富的表现力,对于数据交互和界面交互都采用了Ajax的方式来开发组织的,目前进入了调整和内测阶段。

在整个开发过程中我负责前端开发和游戏设定的工作,第一次在实践中将jQuery作为Javascript的基础库来使用,因为之前也熟悉过jQuery,所以上手也很快,也发现了jQuery是很便捷较之prototype来说。而且jQuery的插件库很丰富,这次在开发的工作量上大大减少了。在这个过程中,我使用了,

  1. jTemplates :一个Json数据绑定灵活的模板,使用很便捷,文档详细,相关网站:http://jtemplates.tpython.com
  2. labs_json:jQuery本身对于Json的转化做的不强,所以采用了这个插件,来实现Json对象序列化和放序列化成字符串。http://plugins.jquery.com/node/7178 http://blog.liquidgear.net/
  3. $.event.special.drag :一个拖拽的特殊事件的支持,相关网站:http://plugins.jquery.com/project/drag http://blog.threedubmedia.com

这次插件用的不多,但是也基本上实现这个游戏的开发。详细的使用说明,就不说了,因为这些插件网站已经叙述的很丰富了。

这个游戏即将公测,大家期待下吧!

03月
13日

flash和Javascript的交互方式

类归于: 做东西 Hbomb 写于 00:38

之前一直是使用,在加载时,在应用的URL里加字符串“?aa=xxx”,在IE下貌似没有问题,但是FF,chrome,等浏览器没法动态相应Javascript修改该字符串。所以最后的解决办法是采用,flash回调Javascript方法获取信息。
呵呵,吸取教训。

03月
01日

3D Canvas 即时演算

类归于: 做东西 Hbomb 写于 15:47

来自于Incredible JavaScript+Canvas 3D demos from Japan! 的报道。
主要使用了JavaScript+Canvas实现了3D 的及时演算,真的很惊人的多边形显示,在chrome上显示的非常完美,但是在safari和firefox显示还是比较卡的。
演示# 1 : 3D贴图映射物理计算
您可以点击画布,使其摇晃。

http://gyu.que.jp/jscloth/

演示 #2: 面向对象的Hatsune Miku 3D 人物

可以拖拽场景,变化观察角度,点击人物,人物会挥动下手中的大蒜

http://gyu.que.jp/jscloth/miku.html

演示 #3: 3D iPod touch 的材质环境反射

可以在材质上反射周围环境的颜色

http://gyu.que.jp/jscloth/touch.html

02月
25日

前端细节:跨浏览器点击界面按钮复制内容到剪贴板

类归于: 做东西 Hbomb 写于 15:53

YOHO!Adsence时,需要一个功能,就是复制内容到剪贴板,通常我们使用的复制到剪贴板的方法就是,采用:

1
 window.clipboardData.setData("Text", txt);

很不幸的是这个复制到剪贴板的方法,只是用于IE,而且如果是IE6新版本,或者IE7会弹出是否允许访问剪贴板的提示,这样一来用户体验就很不好了。特别对于那些非IE用户。于是,我在网上找了下,发现了以下跨浏览器实现的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
copyToClipboard = function(txt)
{
  if(window.clipboardData)
  {
     window.clipboardData.clearData();
     window.clipboardData.setData(”Text”, txt);
  }
  else if(navigator.userAgent.indexOf(”Opera”) != -1)
  {
    window.location = txt;
  }
  else if (window.netscape)
  {
    try
    {
      netscape.security.PrivilegeManager.enablePrivilege(”UniversalXPConnect”);
    }
    catch (e)
    {
      alert(”您的firefox安全限制限制您进行剪贴板操作,请打开’about:config’将signed.applets.codebase_principal_support’设置为true’之后重试”);
      return false;
    }
    var clip = Components.classes[@mozilla.org/widget/clipboard;1].createInstance(Components.interfaces.nsIClipboard);
    if (!clip)
      return;
    var trans = Components.classes[@mozilla.org/widget/transferable;1].createInstance(Components.interfaces.nsITransferable);
    if (!trans)
      return;
    trans.addDataFlavor(’text/unicode’);
    var str = new Object();
    var len = new Object();
    var str = Components.classes[@mozilla.org/supports-string;1].createInstance(Components.interfaces.nsISupportsString);
    var copytext = txt;
    str.data = copytext;
    trans.setTransferData(”text/unicode”,str,copytext.length*2);
    var clipid = Components.interfaces.nsIClipboard;
    if (!clip)
      return false;
    clip.setData(trans,null,clipid.kGlobalClipboard);
  }
}

但是这个办法,并不完美,在chrome和Safari下没法实现复制,而且在firefox下,修改fierfox配置才能支持该功能。所以采用纯JavaScript是无法完成该项任务,浏览器对于复制到剪切板出于安全考虑,都比较谨慎的给实现该功能设置了障碍。于是我继续寻找解决方案,之后看到了一个JavaScript借助flash的剪切板的版本,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function copy(inElement) 
{
  if (inElement.createTextRange) 
  {
    var range = inElement.createTextRange();
    if (range && BodyLoaded==1)
      range.execCommand('Copy');
  }
 else
 {
    var flashcopier = 'flashcopier';
    if(!document.getElementById(flashcopier)) 
    {
      var divholder = document.createElement('div');
      divholder.id = flashcopier;
      document.body.appendChild(divholder);
    }
    document.getElementById(flashcopier).innerHTML = '';
    var divinfo = '<embed src="_clipboard.swf" FlashVars="clipboard='+encodeURIComponent(inElement.value)+'" width="0" height="0" type="application/x-shockwave-flash"></embed>';
    document.getElementById(flashcopier).innerHTML = divinfo;
  }
}

as3的官方参考:

setClipboard () 方法

public static function setClipboard(string:String):void

语言版本 : ActionScript 3.0
Player 版本 : Flash Player 9

用指定的文本字符串替换剪贴板的内容。

注意:出于安全方面的考虑,您无法读取系统剪贴板的内容。 换句话说,不存在相应的 System.getClipboard() 方法。

参数

string:String — 要放置在系统剪贴板上的纯文本字符串,用于替换系统剪贴板上的当前内容(如果有)。

方法来源:http://www.jeffothy.com/weblog/clipboard-copy/

但是这个方法在fp9是可以适用的,但是在fp10之后,这个方法的由于fp10的安全机制的问题,导致不允许脚本去调用fp的as内部方法,于是这个方法在浏览器升级fp后,又是不可以通用了。这样就有了以下方法,人的聪明才知是无限的,既然fp10不允许外部脚本调as的内部方法,为何不反其道行之,采用内部方法调外部的内容能,于是就有了,之下的方法,原理是,在点击触发的dom结构上,蒙一层,这层是透明的flash,当用户点击这个dom结构时,其实同时也点击了这个flash,这样同样还是调setClipboard,而是内部事件触发的,这个方法zeroclipboard,这样就真真实现了跨浏览器的复制到剪贴板的功能。
测试页面如下:点击这里
现在YOHO!Adsense就是采用了这个方法。

02月
22日

Javascript(Jscript)通过ActiveX来操作 Excel

类归于: 做东西 Hbomb 写于 09:47

偶家mm最近被工作上n多excel数据表的操作弄烦了,看的我心里不是滋味,总想帮助下,但是我对excel的宏操作也是菜鸟,最后想来还是使用Javascript来处理逻辑,然后通过ActiveX来操作Excel,基本原理是这样的:读取excel->js处理->输出excel。
js处理这边我就不说了,因为不是本文关注的重点。主要看下通过ActiveX的Excel操作,我主要用到,Excel.Application这个对象。其实查看文档Excel的操作Application、Workbook、Worksheet、Range这几个对象,分别是:Application对象表示整个应用程序,Worksheet对象标示工作表,Workbook对象表示包含Worksheet对象的一个集合,Range则主要用于单元格抽象表示的对象,用于处理单个单元格或成组的单元格。
在Jscrīpt中,通过ActiveXObject对象来启用并返回Automation对象的引用。不管是什么操作首先创建一个ActiveXObject对象。

1
2
var xlsApp = new ActicveXObject(“Excel.Application);
xlsApp .Visible = true;//使Excel可见的

首先看下读取操作:

1
2
3
4
5
6
var wb= xlsApp.Workbooks.open("C:\\temp.xls");//在本地打开一个xls文件。
var aSheet = wb.ActiveSheet;//获取当前的工作表,也可以选定打开哪个工作表,像:wb.Worksheets(1).select()
var rows=wb.aSheet .UsedRange.Cells.Rows.Count;//当前打开表的行数
var cols=wb.aSheet.UsedRange.Columns.Count;//当前打开表的列数
var value= oSheet.Cells(1,1).value;//获取第一行第一列的单元格的值
wb.close();//完成读取操作需要关闭当前的xls

写入Excel文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var xlBook = xlsApp.Workbooks.Add;//添加一个excel集(即一个xls文件)
var xlsheet = xlBook.Worksheets(1);//获取一个工作表
var rang = xlsheet.Cells(i,1).Value="xxx";//往工作表的单元格里添加值
xlsheet.Range(xlsheet.Cells(1,1),xlsheet.Cells(1,6)).Interior.ColorIndex=5//设置单元格背景色为蓝色
xlsheet.Range(xlsheet.Cells(1,1),xlsheet.Cells(1,6)).Font.ColorIndex=4;//设置字体色 
xlsheet.Rows(1).RowHeight = 25;//设置行高
xlsheet.Rows(1).Font.Size=14;//设置字体大小
xlsheet.Rows(1).Font.Name="黑体";//设置字体
xlsheet.Columns("A:D").ColumnWidth =18;//设置列宽
xlsheet.Columns(2).NumberFormatLocal="@";//设置显示字符而不是数字
 range.WrapText  =  true  ;//设置单元格内容自动换行
 range.HorizontalAlignment  =  Excel.XlHAlign.xlHAlignCenter;//设置单元格内容竖直堆砌方式
 range.VerticalAlignment=Excel.XlVAlign.xlVAlignCenter//设置单元格内容水平对齐方式
 range.WrapText  =  true;//设置单元格自动换行
xlsheet.Range(xlsheet.Cells(1,1),xlsheet.Cells(1,4)).mergecells=true;//合并单元格
xls.UserControl = true;  //很重要,不能省略,不然会出问题 意思是Excel交由用户控制
//以下是回收内存
xls=null;
xlBook=null;
xlsheet=null;

参考:

  • http://www.blogjava.net/fool/archive/2006/06/27/55285.html
  • http://www.itjj.net/softtest/tools/20080523/298118.html
  • http://www.javaeye.com/topic/3529
02月
15日

控制网页背景音乐方法一二

类归于: 做东西 Hbomb 写于 04:00

前一阵子,要给yoho.cn的logo加声音彩蛋,我就重新看了下页面加声音方法,之前也看过比较有趣的一些做法。

再加上文宾提供的yahoo的flash叫声,基本上有两种:

  1. flash声音加载方式
  2. 先把声音文件导入flash,编译出连续播放的.swf文件。然后在页面里采用如下js代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    //flash的HTML代码
    var sound_str='<object width="0" height="0" data="xxx.swf" type="application/x-shockwave-flash">
    <param name="id" value="wmsgsound" />
    <param name="quality" value="high" />
    <param name="loop" value="0" /><param name="src" value="xxx.swf" />
    <param name="name" value="wmsgsound" /></object>';
     
    //声音加载方法
    function load_sound()
    {
      var sound = document.createElement("span");
      sound.style.visibility = "hidden";
      sound.innerHTML = yodel_str;
      document.body.appendChild(sound);//把flash的HTML代码插入上面的span内
    };
    //页面触发
    document.getELementById("a").onclick=function()
    {
    load_sound();
    }

    这种方式,必须使用flash才行,还有注意flash的版本,不然IE的object标签会加载flash失败.

  3. embed声音加载方式
  4. 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
    //开始播放
    function startWav(uri)
    {
      stopWav();
      embedEl = document.createElement(”embed”);
      embedEl.setAttribute(”src”, uri);
      embedEl.setAttribute(”hidden”, true);
      embedEl.setAttribute(”autostart”, true);
      document.body.appendChild(embedEl);
    }
    //停止播放
    function stopWav()
    {
      if (embedEl) document.body.removeChild(embedEl);
        embedEl = null;
    }
    //页面触发
    document.getELementById("a").onclick=function()
    {
      startWav('a.wav');
    }

    这种方式,无需使用flash即可加载音频文件,但是用一个缺点,就是有时间的延迟,有一个加载音频文件的延迟,在

    http://softwareas.com/offline-sound-no-flash-no-file 有趣的JavaScript实现的节拍器(没有使用插件)有解决方案,就是把音频文件转成页面的文本编码,但是我试了下,在ie下加载不成功。

所以最后采用flash的方式来做的。
现在点击www.yoho.cn的logo会有叫声了。

11月
11日

学习JavaScript闭包笔记

类归于: 做东西 Hbomb 写于 16:03

之前都没有系统学习过闭包,对于闭包的概念也比较迷糊。今天搜了下关于闭包的资料和文档,有的说的很复杂,也许是翻译的问题吧。之后还是找的了一个比较简单的笔记性说明文档来自于never-online的一篇不错的文章:在Javascript中,什么是闭包(Closure)?

这篇文章的英文原创来自于:http://blog.morrisjohns.com/javascript_closures_for_dummies

于是我对照了原著看了下,更加深了印象,感觉闭包使用的恰当,效果很好的。

首先,闭包是什么?

  • a closure is the local variables for a function - kept alive after the function has returned, or
  • a closure is a stack-frame which is not deallocated when the function returns.
    (as if a ’stack-frame’ were malloc’ed instead of being on the stack!)
  1. 作为一个函数变量的一个引用 - 当函数返回时,其处于激活状态。
  2. 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。


function sayHello(name) {
var text = 'Hello ' + name;
var sayAlert = function() { alert(text); }
sayAlert();
}

以上的代码就表示了闭包的最基本的形式,在一个函数里面包含一个内部函数。
闭包有一个好处,就是变量作用域控制,和内部函数作用域的控制,是外界没法访问内部函数,使代码安全性提高,形成代码的单元。
其实,我还是看到never-online的另一篇
eval解闭包
里面说道:

[edit] Syntax
eval(string [, object])

[edit] Parameters
string
A string representing a JavaScript expression, statement, or sequence of statements. The expression can include variables and properties of existing objects.
object
Non-standard
An optional argument; if specified, the evaluation is restricted to the context of the specified object.

呵呵,这么看来对于JavaScript私有的概念十分的弱了。eval是一个危险的方法,虽然灵活,但是得小心的用,就像goto语句一样有争议了。

最后总结下:
Final points:

* Whenever you use function inside another function, a closure is used.
每当你在一个函数里有另一个函数,表示已使用了闭包。
* Whenever you use eval() inside a function, a closure is used. The text you eval can reference local variables of the function, and within eval you can even create new local variables by using eval(’var foo = …
每当你使用函数里使用eval(),也表示使用了闭包。你执行的文本能够应用这个函数里的局部变量,甚至在eval里创建新的这个函数的局部变量,像这样:eval(’var foo =…
* When you use Function() inside a function, it does not create a closure. (The new function cannot reference the local variables of the function calling Function()).
当你在一个函数里使用Function(),并不会创建一个闭包。(当调用这个新建的函数并不能引用函数的局部变量)
* A closure in JavaScript is like keeping a copy of the all the local variables, just as they were when a function exited.
当一个函数退出时,在JavaScript里一个闭包就像是保持了所有局部变量的拷贝。
——————————————————————–
下面偷懒了,不翻译了,发现翻译措辞很痛苦,虽然看懂了,却不知道咋么表达好,大家一起看e文吧,或者有哪个达人帮忙翻译下。
* It is probably best to think that a closure is always created just on entry to a function, and the local variables are added to that closure.

* A new set of local variables is kept every time a function with a closure is called (Given that the function contains a function declaration inside it, and a reference to that inside function is either returned or an external reference is kept for it in some way).

* Two functions might look like they have the same source text, but have completely different behaviour because of their ‘hidden’ closure. I don’t think JavaScript code can actually find out if a function reference has a closure or not.

* If you are trying to do any dynamic source code modifications ( for example: myFunction = Function(myFunction.toString().replace(/Hello/,’Hola’)); ), it won’t work if myFunction is a closure (Of course, you would never even think of doing source code string substitution at runtime, but…).

* It is possible to get function declarations within function declarations within functions - and you can get closures at more than one level.

* I think normally a closure is the term for both the function along with the variables that are captured. Note that I do not use that definition in this article!

* I suspect that closures in JavaScript differ from those normally found in functional languages.

11月
02日

为什么要使用js框架?

类归于: 做东西 Hbomb 写于 16:31

刚来到一个互联网应用团队,团队的技术leader对我说,你既然是专做web前端的,以后开发尽量少用js框架,应该多自己去写点东西,虽然我们现在使用了prototype的。

我想了想,就问那为什么之前还要用prototype框架呢?回答总结三点,一是时间紧,二是跨浏览器兼容问题,三是没有专业前端开发。这么一来,我就是专业的,所以要在解决跨浏览器兼容性的同时,要在时间足够里,不使用框架开发目前web前端的开发工作,想想要求的确不是很高。

而我主要是在想为什么要用框架,其实代表是一种进步,使用框架并没有什么不好的,常说不要重复去发明轮子一样,可以省的为什么要去不断的去重复,关键不是不使用框架,而是如何理解编写的前人为什么要这么写框架,如果不理解,就不能真正去用好它,使代码会乱,虽然快速实现了功能,但是在维护或复用该功能时发现问题多多。所以,写出有质量的代码才是主要的,至于是否使用框架,而是相对你所要实现的功能或需求而言的,按需开发,需要什么就使用什么技术,什么框架。

例如,你需要写一个,在页面上每隔10秒钟显示一条友好提示,就相当“你知道吗?”这样的功能。

可以这么写:
var tips=
{
   msg:["你可以点击右键打开浏览器的其他选项!","使用“F1”可以获取帮助。","“F5”刷新页面。"],
   current:0,
   show:function()
   {
     document.body.innerHTML=tips.msg[tips.current];
     if(tips.current
        tips.current++;
     else
       tips.current=0;
     setTimeout(tips.show,2000);
    }
};
window.onload=function()
{
   tips.show();
}
以上代码就没有使用任何的框架,因为简单,而且也没有必要去使用框架之类的,一样可以完美的实现这个功能的。
但是如果功能增加了一些要求,如tips的内容需要服务端动态加载,则需要Ajax的支持,另外需要淡入淡出效果,这两要求非常通用,则可以通过框架的支持来实现,可以重构以上的代码,加入框架的应用。例如,prototype或其他什么框架,基本上目前主流框架都有类似的支持,没有必要重新去开发这些,但是对于框架依赖可以抽离出来写,这样就方便解耦。这样代码结构就清晰很多了,便于维护。

所以说,使用框架是站在巨人肩膀上的一种行为,代表一种进步,前提是你要理解它。

10月
29日

JavaScript做的图像渲染,效果很cool,代码很简单

类归于: 过日子 Hbomb 写于 16:49

来自于:http://maettig.com/code/javascript/

网站很简单,但是实现的效果让人眼前一亮

只是简单的算法来实现的,代码很简洁。

10月
23日

JavaScript的弱类型对象[翻译]

类归于: 做东西 Hbomb 写于 17:39

    在JavaRanch Journal看到一片不错的JavaScript的入门文章,感觉不错,十分易懂,决定把它翻译下,一来方便不懂e文的同志分享,二来可以巩固下关于JavaScript对于对象的理解。

 原文地址: http://www.javaranch.com/journal/2008/10/Journal200810.jsp

作者 Stoyan Staefanov

Java 和JavaScript是两种完全不同的语言,但是名称和都是类C的语法很容易却让人混淆。让我们来看看JavaScript不同于Java中如何创建对象的。在Java里,你得先有类,然后再有对象的,又叫做实例化,创建对象要基于那些类的。但是在JavaScript里,是没有类、对象,而是更像是哈希表中的键值对。但是在JavaScript中是如何实例化对象的呢?好,一步步的来讲。

JavaScript 对象

当你在思考关于一个JavaScript对象时,其实就是在思考一个哈希。这里所有的对象就像是一个键值对的集合,那些值则可以包括是任何的对象和函数。当一个对象的其中一个属性是函数时,你就可以称其为方法。

这个就是一个空方法:

Var  myobj = {};

 

现在你可以添加一些有意义的功能到这个对象了:

myobj,name = “My precious”;

myobj.getName = function() {return this.name};

 

这里要注意的事项:

 正如所预期的那样,内部方法是当前对象的应用
你可以添加、调整、删除属性在任何时候,不只是在创建的时候
另一种创建对象的方式是,在创建对象的同时创建属性和方法,就像这样:

Var another  = {

 name: ‘My other precious’,

 getName:function() {

     return this.name;

  }

};

 

这些语法被称之谓文字符号对象,你总之把一切都放在大括号内{},属性则通过逗号隔开。键:值对通过分号隔开。尽管这个不是唯一创建对象的方法。

 

另一种创建JavaScript对象的方法是使用构造函数的方法。这个是构造函数的例子:

Function ShinyObject(name){

    this.name = name;

    this.getName = function(){

   return this.name;

  }

}

 

现在创建一个对象就很想Java 一样了:

var my = new ShinyObject(’ring’);

Var myname = my .getName();//”ring”

 

构造函数的语法没有相对于其他任何函数有所不同,而不同是在在于用法不同。如果你以new的方式调用一个函数,那就会创建并返回一个对象,通过这个,你就有权限在它返回之前修改它。通过约定,构造函数不同于普通函数和方法,名称首字母要大写。

 

 

 

 

 

对象直接创建和构造函数创建,哪个更好呢?嗯,那就取决于你要做的特定的任务。例如,你要创建很多不同的近似的对象,选择使用类构造的方式是个不错的选择。但是如果你创建不会多于一个的单例的话,则可以使用直接对象创建就显得比较简洁了。

好,那么没有里类,是如何实现继承的呢?在讨论这个之前,这里有些小小的惊喜–在JavaScript里函数是正真的对象。

(实际上在JavaScript里大部分分所有的都是对象,除一些原始数据类型-string,boolean,number 和undefined。函数是对象,数组是对象,甚至null也是对象。此外,这些私有的数据类型也可以转化后使用作对象,就像 “string”.length 是有效的。)

 

Function 对象和prototype 属性

在JavaScript里,函数就是对象,可以赋给变量,你可以添加属性和方法等到上面。这里是一个例子:

var myfunc = function(param) {

 alert(param);

};

 

就和这一样:

function myfunc(param) {

 alertparam);

}

 

不管如何你创建的这个函数,你最终可以访问 myfunc里的属性和方法。

alert(myfunc.length);     // 提示1, 数字型的参数

alert(myfunc.toString()); // 提示函数的源代码

 

 

每一个function对象都有一个有趣的特性:都有prototype(原型)这个属性。

当你创建一个function的同时,将自动获取一个指向一个空对象的prototype属性。当然,你能修改这个空对象的属性。

 

alert(typeof myfunc.prototype); // 提示“Object

myfunc.prototype.test = 1; // 完全可以这么做

 

有个问题,prototype有什么用呢?prototype仅可以用在当你引用一个function作为构造函数方式来创建的对象上。当你这么做,这对象就自动获取一个秘密的链接到prototype的属性,然后使之成为自己的属性。真的吗?

 

让我们来看看这个实例。

 

一个新的function

function ShinyObject(name) {

 this.name = name;

}

 

给这个functionprototype属性传参数来添加一些功能:

 

ShinyObject.prototype.getName = function() {

 return this.name;

};

 

使用function像构造函数的方式来创建的对象:

var iphone = new ShinyObject(’my precious’);

iphone.getName(); // 返回”my precious”

 

就像你看到的那样,一个新的对象自动获取这个有权限的prototype属性。然后当有些“免费”获取功能,开始闻到有点像继承和reusability 代码的味道了。

 

以原型的模式继承

 

现在让我们看看你将如何prototype来实现继承。

这里是一个做为父类的构造函数:

 

function NormalObject() {

 this.name = ‘normal’;

 this.getName = function() {

    return this.name;

 };

}

 

第二个构造函数:

 

function PreciousObject(){

 this.shiny = true;

 this.round = true;

}

 

现在继承的部分:

 

PreciousObject.prototype = new NormalObject();

 

啊哈!你可以创建precious对象了,并且将获取所有Normal对象的功能:

 

var crystal_ball = new PreciousObject();

crystal_ball.name = ‘Ball, Crystal Ball.’;

alert(crystal_ball.round); // true

alert(crystal_ball.getName()); // “Ball, Crystal Ball.”

 

注意为什么我们创建一个对象要通过prototype的方式新建或赋予,因为prototype就是一个对象。它不像一个构造函数继承自其他,事实上我们继承是从一个对象的。JavaScript是没有类继承自类的说法,这里只有对象继承自对象。

如果你有一些构造函数继承自NormalObject对象,你或许每次都要new NormalObject()的,但是那是不必要的。甚至整个NormalObject结构体也是不必要的。另一种方式一样做到通过创建一个(单例)的normal object然后使用它就像使用其他的对象。

 

var normal = {

 name: ‘normal’,

 getName: function() {

    return this.name;

 }

};

 

然后PreciousObject能够像这样来继承:

 

PreciousObject.prototype =normal;

 

自从继承者将全部调用代码,已经简单复制属性通过另一种方法来实现。

 

设想你有以下的对象

var shiny = {

   shiny: true,

   round: true

};

 

var normal = {

 name: ‘name me’,

 getName: function() {

    return this.name;

 }

};

 

如何让shiny获取mormal的属性?这里是一个简单的extend()函数,用来循环迭代和复制属性:

 

function extend(parent, child) {

 for (var i in parent) {

    child[i] = parent[i];

 }

}

 

extend(normal, shiny); // 继承

shiny.getName(); // “name me”

 

现在看来这种属性拷贝有一定的开销而感觉不是很好,但是事实上,对于完成大多数任务还不错。你也可以把这个看做实现组合和多重继承的简单途径。

 

Crockford的由父级对象产生对象的方法

Douglas Crockford,是一位JavaScript的宗师和JSON的创始人,他提出了这个有趣的begetObject()方式来实现继承:

 

function begetObject(o) {

 function F() {}

 F.prototype = o;

 return new F();

}

在这里你创建一个临时的构造函数,这样以至于可以使用prototype(原型)的功能,原理是创建一个对象同时继承已存在对象的一些功能。

 

 父级对象:

 

var normal = {

 name: ‘name me’,

 getName: function() {

    return this.name;

 }

};

 

一个新创建继承自父级对象的对象:

var shiny = begetObject(normal);

 

给这个对象新增更多的功能:

 

Shiny.round = true;

 

YUIextend()

 

让我们再来看另一个实现继承的方式,这个更接近于Java,因为在这个方式下,看起来构造函数像是继承自另一个构造函数,因此有点像一个类继承自另一个类。

 

这个方式在非常流行的 YUI JavaScript libraryYahoo! User Interface)这里一个简单版本:

 

function extend(Child, Parent) {

 var F = function(){};

 F.prototype = Parent.prototype;

 Child.prototype = new F();

}

通过这个方法,你传递两个构造函数,第一个(子类)将会通过原型(prototype)属性得到第二个(父类)的所有属性和方法。

 

总结

 

让我们快速总结下关于JavaScript刚才所学习的:

 

没有类的概念

对象继承自对象

对象枚举的方式:var o ={};

构造函数提供类似Java的语法 var o = new Object();

函数和对象的概念

所有函数对象都有一个原型属性

最后,还有讲了一些实现继承的方式,你可以任意的挑选,可以说是手头的任务,个人癖好,团队偏好,或是当前的月相。

 

作者和声明

 

Stoyan Stefanov 是一位资深的Yahoo!开发者, YSlow tool的主导者,开源贡献者,博客作者和技术撰稿人,最近是Packet出版的“Object-Oriented JavaScript”一书 的作者。

 

shiny对象的例子的灵感来自于 Jim Bumgardner撰写的Theory of the Precious Object一书。

 

Douglas Crockford的 beget object - 文章点击这里

 Page 1 of 2  1  2 »