DotNetNuke开发平台--http://www.dnnsun.com
dnnsun
It is only with the heart that one can see rightly...
what is essential is invisible to the eye.
随笔- 27  文章- 1  评论- 140 
博客园  首页  新随笔  联系  管理  订阅 订阅
置顶随笔
[置顶]Blog已迁移到dnnsun.com(最新DotNetNuke咨询平台)
本blog已经好久没有更新了,但作者对dnn的热情仍然在,而且已有一定的成绩,那就是属于我们团队的站点www.dnnsun.com 的诞生

下边就是我最新的一些Blog文章,dnn爱好者不妨看看,一起分享:
1) 你的dnn站点慢了么?
2) 如何定制dnn站点的网站管理和主机管理
3) 如何关联dnn脚本文件SqlDataProvider文件
4) 如何定制安装dnn
5) 再谈dnn的物尽所用(三)
6) 浅谈如何做到dnn物尽所用(二)
7) 浅谈如何做到dnn物尽所用
8) 一些值得推荐的dnn资源
9) 开发DNN模块之Utility * Update *
10) DNN模块开发应用Ajax之Utility
11) 对DNN在国内的影响及其弊端的思考
12) 如何定制登陆页面
13) HTML模版显示DNN模块标题
14) 解析DNN皮肤级别的doctype声明
15) 王者归来—再谈CBO
16) DNN特性之IMC
17) 加速DNN的新举措
18) DNN Object Hydrator -- CBO解析
19) 一些DNN须知的技巧
20) DNN Blog修改日志(优化及扩展)


等等...




posted @ 2008-04-08 23:18 Baldwin 阅读(307) | 评论 (0) | 编辑
2008年5月15日
你需要么,dnn多语言解决方案?
目前dnn多语言解决方案是我这段时间研究的重点,我接下来也许会写几篇相关文章阐述这些问题.
我想本地化是ASP.NET的特性,无疑dnn也会直接支持,但是事实并不是很乐观,那是因为dnn本身也只是在表面上作些文章吧了,如果你想利用dnn实现多语言Portal,那你就错了,除非你重新开发或在模块级别上支持多语言.那dnn究竟支持多语言到何种地步呢?那就是dnn默认支持的多语言只局限于页面标签(Tags,Token etc),比如登陆链接,编辑模块时的字段Label等等,并不是我们通常理解的内容本地化(多语言支持).当然你可以通过两种解决方案来实现多语言支持:
1)模块级别的多语言开发,也许你的内容可能需要存储好几个版本(根据你站点支持的语言总数)
2)站点级别的多语言开发,也就是你需要发布好几个站点(根据你需要支持的语言总数)
目前在DNN模块市场还是有些模块真正做到了支持多语言,比如:
1)MLSkinHelper, PageLocalization Module,Language Selector skin object 等等
http://www.apollo-software.nl/Home/tabid/36/language/en-US/Default.aspx
最经典的范例就是http://declic-video-fx.com/,它利用apollo-software相关模块实现了多语言站点,可以说基本上实现了多语言支持的所有功能.
2)Localization Extensions: Easily implement multilingual portals
http://www.adequation-dotnetnuke.com/en/AboutUs.aspx
该站点的公司主页就是利用来实现了多语言支持,请访问http://www.adequation-informatique.com/en/Home.aspx
3)这是一个免费的模块Magic Content,同时也是DNN Forget下的一个新模块,该模块属于proeder.network.consult公司.
Magic Content is a multi-lingual content publishing module for the DotNetNuke plattform that can be used as a replacement for the current Text/HTML module. It's very easy to use and extends content publishing by many useful features. * one edit tab for each portal locale * advanced edit tab for role based content management * newsletter tab for sending content out via e-mail * replacement token tab.
http://www.codeplex.com/MagicContent
http://www.portalfabrik.net/
相关链接:
How to localization with dnnMenu or solpartMenu?
http://www.dotnetnuke.com/Community/Forums/tabid/795/forumid/76/threadid/224072/scope/posts/Default.aspx
how to localization in skin?
http://www.dotnetnuke.com/Community/Forums/tabid/795/forumid/109/threadid/222245/scope/posts/Default.aspx

更多信息请查看http://www.dnnsun.com/Community/BaldwinsBlog/tabid/67/EntryID/36/Default.aspx
posted @ 2008-05-15 21:06 Baldwin 阅读(343) | 评论 (0) | 编辑
2008年4月25日
如何定制dnn的FckEditor

     先简单介绍一下dnn里边的富文本编辑器(Rich TextEditor)的渊源,也就是我们常说的web在线编辑器,最先dnn版本是集成了FreeTextbox的,但后来由于FreeTextbox商业化了,而且本身FreeTextbox也不是特别的好用,故由于dnn本身的开源性质,最终替换了如今的FckEditor,以下就是FckEditor的一些特性:
1) 多种浏览器兼容,其中包括IE 5.5+ (Windows), Firefox 1.0+, Mozilla 1.3+和Netscape 7+以上浏览器
2) 支持 XHTML 1.0
3) 支持CSS
4) 字体属性编辑
5) 剪切、粘贴、撤销、重复
6) 从word中粘贴文档并自动清理 格式
7) 插入图片,上传图片
8) 表格编辑
9) 插入表单域及其子元素
10) 支持右键菜单
11) 可定制工具栏
12) 皮肤支持
13) 插件(Plugins)模式支持
14) 拼写检查程序
15) 多语言支持以及自动用户语言侦查。
16) 轻量级和快速
17) 自动浏览器侦查和定制
18) 支持多种编程语言,其中包括ASP,CGI,PHP,ASP.NET,Java,ColdFusion,Python等脚本
19) 支持开发者安装和API编程
20) 简单易用! 
21) 开源
这里先着重提及如何定制dnn的FckEditor,在此之前先简单说明一下在dnn中FckEditor的目录结构,目前FckEditor在dnn是作为一个HtmlEditorProviders的形式出现的,也就是dnn已集成了FckEditor并为此提供一个默认的Providersl来管理,将来如果需要替换其他Providers的话也是及其方便的,我想这是dnn里Providers的魅力所在,开发过dnn的程序员都比较清楚,而其FckEditor的根目录就是$rootWebsite/Providers/HtmlEditorProviders/Fck,其中关系到我们如何定制FckEditor比较主要的目录就是默认的FCKeditor和dnn核心添加的Custom这两个目录,如果打开这两个目录看看,你就会比较清楚了,其实FCKeditor这里目录主要就是包含默认的FCKeditor所有的东西,比如skins,plugins,lang(语言包)等等,而Custom这是dnn对默认FCKeditor定制的一些修改配置.比如增加了dnn默认的编辑器工具栏属性:

FCKConfig.ToolbarSets["DNNDefault"] = [
    [
'Source','Preview','-','Templates'],
    [
'Cut','Copy','Paste','PasteText','PasteWord','-','Print','SpellCheck'],
    [
'Undo','Redo','-','Find','Replace','-','SelectAll','RemoveFormat'],
    [
'Bold','Italic','Underline','StrikeThrough','-','Subscript','Superscript'],
    [
'OrderedList','UnorderedList','-','Outdent','Indent'],
    [
'JustifyLeft','JustifyCenter','JustifyRight','JustifyFull'],
    [
'Link','Unlink','Anchor'],
    [
'Image','Flash','Table','Rule','Smiley','SpecialChar','PageBreak'],
    [
'Style','FontFormat'],['FontName','FontSize'],
    [
'TextColor','BGColor'],
    [
'FitWindow','-','About']
] ;
    更多信息... ( http://www.dnnsun.com/Community/BaldwinsBlog/tabid/67/EntryID/32/Default.aspx )
posted @ 2008-04-25 08:56 Baldwin 阅读(324) | 评论 (0) | 编辑
2008年4月8日
Blog已迁移到dnnsun.com(最新DotNetNuke咨询平台)
本blog已经好久没有更新了,但作者对dnn的热情仍然在,而且已有一定的成绩,那就是属于我们团队的站点www.dnnsun.com 的诞生

下边就是我最新的一些Blog文章,dnn爱好者不妨看看,一起分享:
1) 你的dnn站点慢了么?
2) 如何定制dnn站点的网站管理和主机管理
3) 如何关联dnn脚本文件SqlDataProvider文件
4) 如何定制安装dnn
5) 再谈dnn的物尽所用(三)
6) 浅谈如何做到dnn物尽所用(二)
7) 浅谈如何做到dnn物尽所用
8) 一些值得推荐的dnn资源
9) 开发DNN模块之Utility * Update *
10) DNN模块开发应用Ajax之Utility
11) 对DNN在国内的影响及其弊端的思考
12) 如何定制登陆页面
13) HTML模版显示DNN模块标题
14) 解析DNN皮肤级别的doctype声明
15) 王者归来—再谈CBO
16) DNN特性之IMC
17) 加速DNN的新举措
18) DNN Object Hydrator -- CBO解析
19) 一些DNN须知的技巧
20) DNN Blog修改日志(优化及扩展)


等等...




posted @ 2008-04-08 23:18 Baldwin 阅读(307) | 评论 (0) | 编辑
2007年6月26日
再论call和apply

因为继续研究Ajax Framework的原因,更多的接触了call和apply。
故再次论述call和apply,
1)无疑关于call,最简单的解释就是:把隐藏的第一个参数显示化。因为通常一个函数(Function)的调用,会有一个额外的隐藏参数,就是函数(Function)所属的对象(如果没有所特指,则为global(如window)对象),在函数内你可用this关键字访问之。
从call的构造式 -- call(thisArg[,arg1,arg2…] ]);可看出
call(apply)方法可将一个函数的对象上下文(Function Context)从初始的上下文改变为由 thisObj 指定的新对象,这就是利用call(apply)的最大优势。说到此,我们不妨提提所谓的Function Context到底是为何物。先看看下面FunctionContextDemo:

var changed={ item:"banana", act: "eating" };
var original={
        item: 
"chair",
        act: 
"sitting in",
        ask: 
function(){
              
return "who's been "+this.act+" my "+this.item;
        }
};
alert(
"Original : " + original.ask());
alert(
"Not so simple,that have been changed to: " + original.ask.call(changed));

解析上述代码:
最初存在2个对象changed和original,changed即就是一个数组,分别有item和act属性,而original除了具有和changed一样的item和act属性,还具有一个ask函数(询问到底是谁坐在椅子上),故当调用original.ask()时,可以看到意料中的结果:who's been sitting in my chair.而仔细往下看,当我们调用original.ask.call(changed)时,你觉得会出现什么的结果呢?在此,是利用了call把original的方法(函数)ask给与changed对象来执行,原来changed是没有ask方法(函数),如此绑定之后,函数的对象上下文(Function Context)即就是changed对象,故在方法(函数)ask里所调用的this就应该是changed对象,则可推知original.ask.call(changed)的结果应该是:who's been eating my banana.

通过FunctionContextdemo例子可看出如果我们需要在编程过程中需要替换函数的对象上下文(Function Context),call就是不错的选择。
你可以试着把FunctionContextdemo例子修改如下,再看看是什么结果:
var changed={ item:"banana", act: "eating" };
var original={item: "chair",act: "sitting in"};
function ask(){
   return "who's been "+this.act+" my "+this.item;
}
alert("Original : " + ask.call(original));
alert("changed: " + ask.call(changed));

2)javascript如何利用call来模拟面向对象中的继承的,而且可以实现多重继承

// 多重继承
function base1() {
    
this.member = " base1_Member";
    
this.showSelf = function() {
        window.alert(
this.member);
    }
}
function base2() {
    
this.person = " base2_Member";
 
this.act = " is dancing happily";
    
this.showAction = function() {
        window.alert(
this.person + this.act);
    }
}
function extend() {
    base1.call(
this);
    base2.call(
this);
}
window.onload
=function(){
   
var demo = new extend();
   demo.showSelf();
   demo.showAction();
}

但仔细深入看看,这样的继承是有问题的,直接在类函数体里面定义成员方法,将导致每个实例都有副本,重复占用了内存。
最为优雅简洁的方式应该算是基于原型(prototype)继承。
3)接下来我们再次来看看javascript框架prototype里是如何利用apply来创建一个定义类的模式:
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
};
解析:
从代码看,该对象仅包含一个方法:Create,其返回一个函数,即类。但这也同时是类的构造函数,其中调用initialize,而这个方法是在类创建时定义的初始化函数,如此就可以实现prototype中的类创建模式.目的是规定如此一个类创建模式,让类的初始化函数名一定是initialize(),而this.initialize.apply(this, arguments);(令人有些费解)则是保证initialize一定会在类的实例创建后调用,既方便管理又体现Object-Oriented的思想。

注意: 里边的this其实是同一对象,即相当于类本身调用自己的构造函数来创建Class对象! 因为apply方法的第二个参数本身要求是一个数组,所以传递给该函数的参数也传递给类的initialize方法,如果直接写为 this.initialize(arguments); 则所有的参数是作为一个数组传递给了initialize构造函数。

var vehicle=Class.create();
vehicle.prototype
={
    initialize:
function(type){
        
this.type=type;
    }
    showSelf:
function(){
        alert(
"this vehicle is "+ this.type);
    }
}

var moto=new vehicle("Moto");
moto.showSelf();

4) 活用apply(javascript框架prototype的事件绑定):
Function.prototype.bind = function() {
  var __method = this; 
  var args = $A(arguments); 
  var object = args.shift();
  return function() { 
    // 调用函数的apply方法执行函数, 其中的object为目标对象, args为bind方法中的参数列表(除了第一个参数以外的参数构成的数组)
    return __method.apply(object, args.concat($A(arguments)));// 事实上, 这里的$A(arguments)一定是一个空数组
  }
}
代码解析:
该bind用途在于将某个函数绑定到特定的函数去执行,
a) var __method = this;这首先把Function Context重新赋值到一个本地变量,使得在Closure(这是一个javascript的特性,可解释为"闭包")中都能访问到,如此在下边就可以方便获取了。它实质就是bind方法的调用者, 是一个函数对象。
b) var args = $A(arguments);这里因为arguments本就是一个类数组的对象,通过$A(arguments)将传入到bind方法的参数都转化为array.
c) var object = args.shift();通过截取args的第一个参数获取Target Object(目标对象),此时args为除了第一个参数以外的参数构成的数组(array)
d) 这是最关键的一步,返回一个新的函数对象(不带有任何的参数的函数),在此通过apply把__method(bind方法的调用者)绑定到Target Object(目标对象),并给与除了Target Object(目标对象)之外的所有参数构成的数组args.concat($A(arguments)),最终Target Object(目标对象)就可执行__method了。
如此费劲周折的绑定某一个函数所换来的优势是,从此你不需要顾及Function Context的混乱所带来的额外顾虑。

posted @ 2007-06-26 19:31 Baldwin 阅读(970) | 评论 (6) | 编辑
2007年6月21日
MarqueeNews2.2发布
     摘要: DNN Extendable Module....  阅读全文
posted @ 2007-06-21 09:47 Baldwin 阅读(1700) | 评论 (5) | 编辑
2007年1月17日
ControlPanel研究系列二:简单Ajax模式的ControlPanel(SimplAjax)

      自从上次写了点关于ControlPanel的一些简单介绍后,由于懒惰的原因,一直没有在提笔写ControlPanel的研究心得了,惭愧啊!
      请参看ControlPanel研究系列一:简单引入控制窗格(ControlPanel)
      现在DNN已经升级到了4.4.0版本了,我只能奋起直追了,大家都知道,DNN在引入了asp.net 2.0框架后已经优化了很多,自然
功能及其相关的业务更是有所完善了,ClientAPI的重写更是可以让DNN注入了最热火的Ajax技术的应用。经过对ClientAPI的略为研究,我也不免手痒痒了,于是我最先入手就是尝试ControlPanel的修改,使其支持Ajax的应用。
      我把原先的classic.ascx进行修改,现把其文件名改为SimplAjax,这是必然的, :)
     首先声明,此版本只针对4.3.5以上的DNN框架。当然你也可以修改符合你的DNN版本,下载中含有源代码。
      为了支持dnn的Ajax应用,必须实现接口IClientAPICallbackEventHandler,该接口需要实现函数

Public Function RaiseClientAPICallbackEvent(ByVal eventArgument As String) As String Implements DotNetNuke.UI.Utilities.IClientAPICallbackEventHandler.RaiseClientAPICallbackEvent
 
'TO DO Somthings
 End Function
      接下来,就是考虑你需要实现怎样的功能了,在此因为classic.ascx就是一个DNN自带最为简单方便的ControlPanel,所具有的功能就是添加模块,编辑页面等相关操作,其中具有当你在下拉框选中需要模块时,你可查看该模块的一些描述信息以便知道其具体功能应用。只是每次你查看时都需要刷新页面一次,而现在我就想把这次页面刷新页面给免了,让DNN的Ajax来实现。
      好,现在开始来实现我们需要的业务代码。主要有注册脚本和激发回传信息事件,具体代码如下:
        ''' <summary>
        ''' 注册脚本
        ''' </summary>
        ''' <remarks></remarks>
        Private Sub RegisterScript()
            
'these won't be necessary in next release after 3.2.0
            If ClientAPI.BrowserSupportsFunctionality(ClientAPI.ClientFunctionality.XMLHTTP) _
              
AndAlso ClientAPI.BrowserSupportsFunctionality(ClientAPI.ClientFunctionality.XML) Then
                ClientAPI.RegisterClientReference(
Me.Page, ClientAPI.ClientNamespaceReferences.dnn_xml)
                ClientAPI.RegisterClientReference(
Me.Page, ClientAPI.ClientNamespaceReferences.dnn_xmlhttp)

                
'Only this line will be necessary after 3.2
                Dim cbReference As String = ClientAPI.GetCallbackEventReference(Me, "arg", "successFunc", "ctx", "errorFunc")
                
Dim callbackScript As StringBuilder = New StringBuilder
                callbackScript.Append(
" function StartAsynCall(arg,ctx) ")
                callbackScript.Append(
" { ")
                callbackScript.Append(cbReference)
                callbackScript.Append(
" } ")
                Page.ClientScript.RegisterClientScriptBlock(
Me.GetType(), "CallServer", callbackScript.ToString, True)
                
Me.imgHelpShow.Attributes.Add("onclick", "AsynCallProcess('" & Me.ClientID & "')")

                
Me.cboDesktopModules.Attributes.Add("onchange", "javascript:toggleInfos();")
                ClientAPI.RegisterClientVariable(Page, 
"ctx", Me.ClientID, True)
                ClientAPI.RegisterClientVariable(Page, 
"appPath", Me.ClientID, True)

            
End If
        
End Sub

        
''' <summary>
        ''' 激发回传信息事件
        ''' </summary>
        ''' <param name="eventArgument"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function RaiseClientAPICallbackEvent(ByVal eventArgument As String) As String Implements DotNetNuke.UI.Utilities.IClientAPICallbackEventHandler.RaiseClientAPICallbackEvent
            
Return GetModuleInfos(eventArgument)
        
End Function
       不知你是否注意到在实现接口函数RaiseClientAPICallbackEvent时调用的GetModuleInfos(eventArgument)?该函数就是进行回传服务器信息(即获取的模块信息)到客户端,而在客户端,通过已注册的脚本函数successFunc进行处理所回传的信息。
''' <summary>
        ''' 获取模块的简单描述信息
        ''' </summary>
        ''' <param name="sModuleId">模块Id</param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Private Function GetModuleInfos(ByVal sModuleId As String) As String

            
Dim modulesInfo As String = ""
            
Try
                
Dim objDesktopModules As New DesktopModuleController
                
Dim objDesktopModule As DesktopModuleInfo

                objDesktopModule 
= objDesktopModules.GetDesktopModule(Int32.Parse(sModuleId))
                
If Not objDesktopModule Is Nothing Then
                    modulesInfo 
= objDesktopModule.Description
                
End If

            
Catch exc As Exception    'Module failed to load
                ProcessModuleLoadException(Me, exc)
            
End Try

            
Return modulesInfo

        
End Function

function successFunc(result, ctx)
{
    
var oDiv = dnn.dom.getById('divDescription');
    
if (oDiv.style.display == 'none') {
        oDiv.style.display 
= 'block';
    }
    
var oInfo = dnn.dom.getById(ctx + '_lblDescription'); 
    oInfo.innerHTML 
= result;
    dnn.dom.getById(ctx 
+ '_imgHelpShow').src = "/dnndev/images/reset.gif";
}
    到此,整个回调过程就算结束了。
    demo:
    回调前:
   
   后调后:
   
     当然,这只是我的一个简单在DNN使用ClientAPI的尝试。我还将开发出全新的ControlPanel,现在还在测试中,demo:

      下载地址:http://www.dnnsun.com/FreeDownload/tabid/59/Default.aspx
     
      这是简单的安装步骤:
      1 把SimpleAjax.ascx.vb  SimpleAjax.ascx  SimpleAjax.js SimpleAjax.css四个文件拷贝到$yourDNNRoot\Website\admin\ControlPanel文件下
      2 把SimpleAjax.ascx.resx SimpleAjax.ascx.zh-CN.resx拷贝到$yourDNNRoot\Website\admin\ControlPanel、App_LocalResources文件下
      3  以host用户登录,在主机管理(Host)下选择SQL服务(SQL),将下边代码拷贝并粘贴到框内,把当作脚本运行选项打勾,点击执行。 
      INSERT {databaseOwner}{objectQualifier}ModuleControls
       (ControlKey, 
       ControlSrc, 
       ControlType)
      VALUES
       ('CONTROLPANEL:BaldwiBar', 
       'Admin/ControlPanel/BaldwiBar.ascx',
       -3)
      如图:
      
      注意:把当作脚本运行选项打勾。 :)
      4 在主机管理(Host)下选择主机管理,再选择高级设置下的其他设置,其中有控制窗格选项,在其下拉菜单下选择SimpleAjax,最后更新即可
      
      
       如有不清楚之处,请告知.....      

posted @ 2007-01-17 22:25 Baldwin 阅读(1834) | 评论 (1) | 编辑
2006年9月1日
动态显示更多信息(toggle_visible函数的运用)
       当你需要显示很多信息,可页面却再没有足够的空间可以容纳的时候,你一般会如何解决类似问题呢?或硬塞进页面而不管是否美观简洁么?还是就让用户不断拉动滚动栏而不管用户是否觉得麻烦?还是增建新页面而迫使用户去不耐烦在不同页面之间跳转呢?我想如果你使真的想作一个美观而简洁的Web网站的话,上述提到的想法应该在你脑海中一闪而过时就应该被否定的!而在同一个页面动态的显示信息的想法无疑是一个不错的主意,在此我提供两种实现类似效果的代码:
<!--简单的动态显示
SimpleToggleVisibleElement.html
-->
<html>
<head>
<script type='text/javascript'>
    
function toggle_visible (elName) {
        
var el = document.getElementById (elName);
        
var isVisible = (el.style.visibility == "hidden") ? true : false;

        el.style.visibility 
= isVisible ? "visible" : "hidden";
        el.style.display 
= isVisible ? "inline" : "none";
    }
</script>
</head>
<body>
<table border=0 width="35%" cellpadding="3">
<tr>
    
<td bgcolor="#404080" onclick="toggle_visible('divQOTD');">
        
<font color="#FFFFFF">
        Quote of the Day
        
</font>
    
</td>
</tr>
<tr>
    
<td bgcolor="#E0E0E0">
        
<div id="divQOTD">
            
<em>"Outside of a dog, a book is man's best friend. 
            Inside of a dog it's too dark to read."
</em>
            -- Groucho Marx
<br>
        
</div>
    
</td>
</tr>
</table>
</body>
</html>
注意:上边代码el.style.display必须设置,不然即使你设置了el.style.visibility属性,那原先该块状元素所占有的区域并未释放,虽然它已不可见!而设置了el.style.display则可空出了需要的空间,如此才达到我们的目的! ^_^
<!--利用dl dt dd 及image动态显示信息
ImageToggleVisibleElement.html
-->
<html>
<head>
<style>
dl
{margin-top:0px;margin-bottom:0px}
ul
{ margin-left:-12px;}
li
{ list-style: url("arrow.gif");} 
dt
{ background-color: #000000;padding-left:5px;padding-top:2px;padding-bottom:2px;color:#ff9900}
</style>
<script type='text/javascript'>
    
//折叠标题
    function toggleTitle(oTitle,oImage,me){
        
if( oTitle.style.display == "none"){
            
//oTitle.style.display="inline";
            oTitle.style.display="";
            oImage.src 
= "blueup.gif";
            me.title 
= "单击此处可以折叠显示信息";
        }
else{
            oTitle.style.display 
= "none";
            oImage.src 
= "bluedrop.gif";
            me.title 
= "单击此处可以展开显示信息";
        }
    }
</script>
</head>
<body>
<table width="35%" bgcolor="#E0E0E0">
    
<tr>
        
<td>
            
<dl>
                
<dt onclick="toggleTitle(content_01,img_01,this);" title="单击此处可以折叠显示信息">
                  
<img src="blueup.gif" id="img_01">最新书籍
                
</dt> 
                
<dd id="content_01">
                    
<ul>
                    
<li>Ajax Hacks(Ajax解密)</li>
                    
<li>Ajax in Action(Ajax实战)</li>
                    
<li>Javascript的早餐(英文版)</li>
                    
<li>Pragmatic Ajax(Ajax之道)</li>
                    
</ul>
                
</dd> 
            
</dl>
        
</td>
    
</tr>
</table>
</body>
</html>
代码下载(完整文件):/Files/sunwangji/js.zip
posted @ 2006-09-01 17:04 Baldwin 阅读(1256) | 评论 (7) | 编辑
2006年8月21日
全面理解javascript的caller,callee,call,apply概念(修改版)

(注:在看到大家如此关注JS里头的这几个对象,我试着把原文再修改一下,力求能再详细的阐明个中意义  2007-05-21)
在提到上述的概念之前,首先想说说javascript中函数的隐含参数:arguments

Arguments

该对象代表正在执行的函数和调用它的函数的参数。

[function.]arguments[n]
参数
function :选项。当前正在执行的 Function 对象的名字。
n :选项。要传递给 Function 对象的从0开始的参数值索引。

说明

Arguments是进行函数调用时,除了指定的参数外,还另外创建的一个隐藏对象。Arguments是一个类似数组但不是数组的对象,说它类似数组是因为其具有数组一样的访问性质及方式,可以由arguments[n]来访问对应的单个参数的值,并拥有数组长度属性length。还有就是arguments对象存储的是实际传递给函数的参数,而不局限于函数声明所定义的参数列表,而且不能显式创建 arguments 对象。arguments 对象只有函数开始时才可用。下边例子详细说明了这些性质:

//arguments 对象的用法。
function ArgTest(a, b){
   
var i, s = "The ArgTest function expected "
;
   
var numargs = arguments.length;     // 获取被传递参数的数值。

   var expargs = ArgTest.length;       // 获取期望参数的数值。
   if (expargs < 2)
      s 
+= expargs + " argument. "
;
   
else

      s 
+= expargs + " arguments. ";
   
if (numargs < 2
)
      s 
+= numargs + " was passed."
;
   
else

      s 
+= numargs + " were passed.";
   s 
+= "\n\n"

   
for (i =0 ; i < numargs; i++){      // 获取参数内容。
   s += "  Arg " + i + " = " + arguments[i] + "\n";
   }
   
return(s);                          // 返回参数列表。

}


在此添加了一个说明arguments不是数组(Array类)的代码:

Array.prototype.selfvalue = 1;
alert(
new
 Array().selfvalue);
function
 testAguments(){
    alert(arguments.selfvalue);
}


运行代码你会发现第一个alert显示1,这表示数组对象拥有selfvalue属性,值为1,而当你调用函数testAguments时,你会发现显示的是“undefined”,说明了不是arguments的属性,即arguments并不是一个数组对象。
在此附加上大家推荐的一个简单方法:

alert(arguments instanceof Array);
alert(arguments 
instanceof Object);



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

// caller demo {
function callerDemo() {
    
if (callerDemo.caller) {
        
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 对象的一个成员,它表示对函数对象本身的引用,这有利于匿名
函数的递归或者保证函数的封装性
,例如下边示例的递归计算1到n的自然数之和。而该属性
仅当相关函数正在执行时才可用。还有需要注意的是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)
}

比较一般