??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲天堂男人,国产成人精品午夜视频免费,另类视频一区二区三区http://www.aygfsteel.com/zengke/category/16332.htmlzh-cnThu, 01 Mar 2007 02:35:46 GMTThu, 01 Mar 2007 02:35:46 GMT60利用XMLHTTP实现ASP.NET无刷新提?http://www.aygfsteel.com/zengke/articles/90359.htmlWed, 27 Dec 2006 10:17:00 GMThttp://www.aygfsteel.com/zengke/articles/90359.htmlhttp://www.aygfsteel.com/zengke/comments/90359.htmlhttp://www.aygfsteel.com/zengke/articles/90359.html#Feedback0http://www.aygfsteel.com/zengke/comments/commentRss/90359.htmlhttp://www.aygfsteel.com/zengke/services/trackbacks/90359.html 在一些页面处理中Q如果需要多ơ进行后台提交处理的话,׃不停的刷新页面,很烦人,特别是机器配|不好或者网l状况不好的情况下,更加昑־让h隑֏?/font>

q种情况下我们可以利用XMLHTTP来实Ch的提交,q在做asp的时候就有不这L应用Q在asp.net里用也是一L?/font>

首先Q新Z个页面,命名Send.aspx, 用来做需要提交的面Q另一个页面do.aspx, 用来做处理提交的面?/font>

在Send.aspx面中,有一个input输入框,作ؓ我们需要提交到后台的数据,

<input id="txtUser" type="text" runat="server">
另外写一个js的提交方法,代码如下Q?/font>

function SendData(){
var xh = new ActiveXObject("MSXML2.XMLHTTP");  
xh.open("POST","do.aspx?ID=1",false);
xh.send(document.all.txtUser.value);
alert(xh.responseText);//打印XMLHTTP的返回数据}q个jsҎ非常单,定义一个XMLHTTP对象Q然后就调用openҎ和sendҎQ就可以?
再在面中用一个button来调用该ҎQ发送到do.aspx?/font>

在处理的面do.aspx,在对应的cs文gdo.aspx.cs中,q样来接收发送过ȝ数据Q?/font>

int id = 0;
if(Request.Params["ID"] != null)
{   
//接收从url中传递过来的参数   
id = int.Parse(Request.Params["ID"]);}
//接收从xh.send()Ҏ中传递过来的数据
System.IO.Stream stream = Request.InputStream;
System.IO.BinaryReader br = new System.IO.BinaryReader(stream, System.Text.Encoding.Default);
int len = int.Parse(stream.Length.ToString());
byte[] b = br.ReadBytes(len);
//q里可以Ҏ传递过来的参数和数据进行各U处?br />////q回l发送页面的数据Q通过Response.Write()来传?br />//q里发送过来的参数和数据返?br />Response.Write(id + System.Text.Encoding.Default.GetString(b));
整个q程p样OK了?br />注意Q在do.aspx文g的html代码面中,如果存在M的前C码,都会作ؓsend()h的返回内容,一q返回到xh.responseText中?/font>


另外Q可以用html面来替代上面的Send.aspxQ按照相同的ҎQ来实现静态页面的数据提交?/font>

 



2006-12-27 18:17 发表评论
]]>
l典JavaScript代码(?http://www.aygfsteel.com/zengke/articles/89926.htmlMon, 25 Dec 2006 08:13:00 GMThttp://www.aygfsteel.com/zengke/articles/89926.htmlhttp://www.aygfsteel.com/zengke/comments/89926.htmlhttp://www.aygfsteel.com/zengke/articles/89926.html#Feedback0http://www.aygfsteel.com/zengke/comments/commentRss/89926.htmlhttp://www.aygfsteel.com/zengke/services/trackbacks/89926.html |页l典代码
1. 彻底屏蔽鼠标右?无右键菜?
<body oncontextmenu=window.event.returnvalue=false>

也可以用于网中Table框架?
<table border oncontextmenu=return(false)><td>no</table>


2.取消选取、防止复?
<body onselectstart=return false>


3.不准_脓
<body onpaste=return false>


4.防止复制
<body oncopy=return false; oncut=return false;>


5.IE地址栏前换成自己的图?
<link rel=Shortcut Icon href=favicon.ico>

说明Q关于favicon.ico文g的制作。你可以先在FW中做一个图片,属于你自q点一个小图标。然后在ACD see文件属性改?.icoQ然后将你做?.ICO文g传到你的服务器目录中Q然后就可以使用以上代码来实玎ͼ当别人登陆你的站ҎQ地址栏里使用的就是你自定义的图标了?


6.可以在收藏夹中显C出你的图标
<link rel=Bookmark href=favicon.ico>

说明Q制作方法和上面的一栗只是显C的方式不同Q这个是在别人收藏你的网地址时显C的个性图标?


7.关闭输入?
<input style=ime-mode:disabled>

说明Q这D代码是在表格提交时用到的。也是在输入数据时不可以用其他输入法模式?


8.永远都会带着框架
<script language=javascript><!--
 if (window == top)top.location.href = frames.htm;// --></script>

说明Qframes.htmZ的网,q也是保护页面的一U方?


9.防止被hframe
<SCRIPT LANGUAGE=javascript><!--
 if (top.location != self.location)top.location=self.location;
// --></SCRIPT>


10.|页不能被另存?
<noscript><iframe src=*.html></iframe></noscript>
说明Q?lt;noscirpt>的用法很q,其中一条就是可以JSq告失效?


11.查源文g
<input type=button value=查看|页源代?
onclick=window.location = 'view-source:'+ target=_blank>[url]http://bbs.055.cn/test.htm[/url]';>


12.COOKIE脚本记录Q有很大的用处哦

function get_cookie(Name) {
var search = Name + =

var returnvalue = ;

if (documents.cookie.length > 0) {

offset = documents.cookie.indexOf(search)

if (offset != -1) { // if cookie exists

offset += search.length

// set index of beginning of value

end = documents.cookie.indexOf(;, offset);

// set index of end of cookie value

if (end == -1)

end = documents.cookie.length;

returnvalue=unescape(documents.cookie.substring(offset, end))

}

}

return returnvalue;

}


function loadpopup(){

if (get_cookie('popped')==''){

openpopup()

documents.cookie=popped=yes

}

}

说明Q以上是JS代码Q请自己加v始符和结束符


13.内框?lt;IFRAME>使用
Iframe标记的用格式是:   

<iframe src=URL width=x height=x scrolling=[OPTION] frameborder=x
name=main></iframe>
srcQ文件的路径Q既可是HTML文gQ也可以是文本、ASP{  
width、heightQ内部框架区域的宽与高;   
scrolling:当SRC的指定的HTML文g在指定的区域不显不完Ӟ滚动选项Q如果设|ؓNOQ则不出现滚动条Q如为AutoQ则自动出现滚动条;如ؓYesQ则昄;  FrameBorderQ区域边框的宽度Qؓ了让“内部框架“与邻近的内容相融合Q常讄??
name:框架的名字,用来q行识别?
比如:  当你想用父框架控制内部框架时Q可以用: target=框架的名字来控制?

例子Q?lt;iframe name=mm src=http://bbs.055.cn;; width=100% height=100% marginwidth=0 marginheight= ... ot; frameborder=0 scrolling=no></iframe>

14.自动跌{
在源代码中的<head>?lt;/head>加入如下代码Q?br /><meta http-equiv=refreshcontent=3;URL=http://bbs.055.cn; charset=gb2312>

说明Qcontent=3 表示3U刷新到URL


15.如何改变链接的鼠标Ş?br />只需在链接上加上q一代码p的了
或者跟上面的用CSS写也?/font>

style=cursor:hand       style=cursor:crosshair
style=cursor:text       style=cursor:wait
style=cursor:move       style=cursor:help
style=cursor:e-resize     
style=cursor:n-resize
style=cursor:nw-resize     style=cursor:w-resize
style=cursor:s-resize     
style=cursor:se-resize
style=cursor:sw-resize

以上代码你只需要加到连接或是页面的style区里可以实现鼠标多样化?/font>


16.全屏昄
<form>
<div align=center>
<input type=BUTTON name=FullScreen value=全屏昄 onClick=window.open(document.location, 'big', 'fullscreen=yes')>
</div>
</form>

把它攑ֈ<body>Z?/font>


17.设ؓ首页

<script language=javascript>
<!--
function defaul_home(){
this.home.style.behavior='url(#default#homepage)';this.home.setHomePage([url]http://bbs.055.cn/[/url]';
}
var focusok=false;
if (navigator.appName == Netscape{
focusok=true;
}
vers=navigator.appVersion;
if (navigator.appName == Microsoft Internet Explorer{
pos=vers.lastIndexOf('.');
vers=vers.substring(pos-1,vers.length);
}
proper_version=parseFloat(vers);

if(proper_version>=5){
focusok=true;
}
function launchstock1(htmlurl){
var stock=window.open(htmlurl,stock,top=2,left=2,toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,
resizable=no,width=700,height=510;
if(focusok){
stock.focus();
}
return true;
}
function launchstock(){
var stock=window.open(,stock,top=2,left=2,toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,

resizable=no,width=700,height=510;
if(focusok){
stock.focus();
}
return true;
}
// -->
</script>
<a href=# name=home onClick=defaul_home(); title===E代时?=>设ؓ首页</a>


18.q里是加入收藏夹的代?/font>

<a href=# onClick=window.external.addFavorite([url]http://bbs.055.cn[/url]';.'拂晓雅阁') target=_self title=拂晓雅阁>加入收藏?lt;/a>


19.flash囄效果
以下代码加入<head>区域
<SCRIPT language=javascript>
<!--
function makevisible(cur,which){
if (which==0)
cur.filters.alpha.opacity=100
else
cur.filters.alpha.opacity=20
}

//-->

</SCRIPT>
以下代码加入<body>区域
<img src=http://bbs.055.cn/images/logo.gif;; style=filte ... nbsp;onMouseOver=makevisible(this,0) onMouseOut=makevisible(this,1) width=63 height=56> //囄地址误己改


20.load q度?/font>

<table cellspacing=0 cellpadding=0 bgcolor=#FFFFFF width=40% id=P><tr><td>
<table cellspacing=0 cellpadding=0 bgcolor=#0000FF height=18 id=Q><tr><td></td></tr></table></td></tr></table>
</center>
<script language=javascript>
var R = 0; load();
function load() {R = R + 2; Q.style.width = R + %; time= setTimeout(load(),50);
if (R > 100) {clearTimeout(time); P.style.width=0}}
</script>
27 全屏
<script language=javascript>
window.open('index.asp','','fullscreen=1');
</script>


21.背景囄滚动

<body scroll=no background=images/bg.jpg link=#00FF00 alink=#FF0000 vlink=#00FF00 bgcolor=#000080 topmargin=8>
<script language=javascript>
var backgroundOffset = 0;
var bgObject = eval('document.body');
function scrollBG(maxSize) {backgroundOffset = backgroundOffset + 1;
if (backgroundOffset > maxSize) backgroundOffset = 0;
bgObject.style.backgroundPosition = 0  + backgroundOffset;}
var ScrollTimer = window.setInterval(scrollBG(410), 20)
</script>


22.|页不会被缓?/font>

HTMl|页
<META HTTP-EQUIV=pragma CONTENT=no-cache>
<META HTTP-EQUIV=Cache-Control CONTENT=no-cache, must-revalidate>
<META HTTP-EQUIV=expires CONTENT=Wed, 26 Feb 1997 08:21:57 GMT>
或?lt;META HTTP-EQUIV=expires CONTENT=0>
ASP|页
 Response.Expires = -1
 Response.ExpiresAbsolute = Now() - 1
 Response.cachecontrol = no-cache
PHP|页
header(Expires: Mon, 26 Jul 1997 05:00:00 GMT;
header(Cache-Control: no-cache, must-revalidate;
header(Pragma: no-cache;


23.

<%
'定义数据库连接的一些常?br />Const adOpenForwardOnly   = 0 '游标只向前浏览记录,不支持分cRecordset、BookMark
Const adOpenKeyset     = 1 '键集游标Q其他用户对记录说做的修改将反映到记录集中,但其他用户增加或删除记录不会反映到记录集中。支持分cRecordset、BookMark
Const adOpenDynamic     = 2 '动态游标功能最强,但耗资源也最多。用户对记录说做的修改,增加或删除记录都反映到记录集中。支持全功能览(ACCESS不支??br />Const adOpenStatic     = 3 '静态游标,只是数据的一个快照,用户对记录说做的修改Q增加或删除记录都不会反映到记录集中。支持向前或向后Ud
Const adLockReadOnly    = 1 '锁定cdQ默认的Q只读,不能作Q何修?br />Const adLockPessimistic   = 2 '当编辑时立即锁定记录Q最安全的方?br />Const adLockOptimistic   = 3 '只有在调用UpdateҎ时才锁定记录集,而在此前的其他操作仍可对当前记录q行更改、插入和删除{?br />Const adLockBatchOptimistic = 4 '当编辑时记录不会被锁定,而更攏V插入和删除是在批处理方式下完成?br />Const adCmdText = &H0001
Const adCmdTable = &H0002
%>


24.最化、最大化、关闭窗?br /><object id=hh1 classid=clsidDB880A6-D8FF-11CF-9377-00AA003B7A11>
<param name=Command value=Minimize></object>
<object id=hh2 classid=clsidDB880A6-D8FF-11CF-9377-00AA003B7A11>
<param name=Command value=Maximize></object>
<OBJECT id=hh3 classid=clsid:adb880a6-d8ff-11cf-9377-00aa003b7a11>
<PARAM NAME=Command value=Close></OBJECT>
<input type=button value=最化 onclick=hh1.Click()>
<input type=button value=最大化 onclick=hh2.Click()>
<input type=button value=关闭 onclick=hh3.Click()>

说明Q本例适用于IE


25.判断上一늚来源

asp?
request.servervariables(HTTP_REFERER
java script:
document.referrer


26.光标是停在文本框文字的最?/font>

<script language=javascript>
function cc()
{
 var e = event.srcElement;
 var r =e.createTextRange();
 r.moveStart('character',e.value.length);
 r.collapse(true);
 r.select();
}
</script>
<input type=text name=text1 value=123 onfocus=cc()>

说明Q适用于表格数据提?/font>

 



2006-12-25 16:13 发表评论
]]>
两个客户端操作TreeView节点CheckBox的小例子http://www.aygfsteel.com/zengke/articles/87094.htmlMon, 11 Dec 2006 16:05:00 GMThttp://www.aygfsteel.com/zengke/articles/87094.htmlhttp://www.aygfsteel.com/zengke/comments/87094.htmlhttp://www.aygfsteel.com/zengke/articles/87094.html#Feedback0http://www.aygfsteel.com/zengke/comments/commentRss/87094.htmlhttp://www.aygfsteel.com/zengke/services/trackbacks/87094.html 

最q在论坛上回{了一些关于客L操作TreeView节点选中的问题,在网友提供的代码基础上做了两个例子。可惜原贴已l丢׃Q整理一下写成文吧
Z书写方便Q这两个例子没有采用codebehind方式Q复制即可运?br />
W一个例子是当取消或选中节点选中状态时Q子节点也做相应的取消或选中变化
需要注意的是如果要初始讄TreeNode为选中状态,只能在客L讄。如果在服务器端讄TreeNode为选中状态,则在客户端用getAttribute("Checked")Q得到的值永q是true?/p>

<%@ Register TagPrefix="iewc" Namespace="Microsoft.Web.UI.WebControls" Assembly="Microsoft.Web.UI.WebControls, Version=1.0.2.226, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<HTML>
 <HEAD>
  <script language="C#" runat="server">
   private void Page_Load(object sender, System.EventArgs e)
   {   
    TreeView1.Attributes.Add("oncheck","tree_oncheck(this)");
   }
  </script>
  <script language="javascript">
<!--
//初始化选中节点
function initchecknode()
{
 var node=TreeView1.getTreeNode("1");
 node.setAttribute("Checked","true");
 setcheck(node,"true"); 
 FindCheckedFromNode(TreeView1);
}
//oncheck事g
function tree_oncheck(tree)
{
 var node=tree.getTreeNode(tree.clickedNodeIndex);
 var Pchecked=tree.getTreeNode(tree.clickedNodeIndex).getAttribute("checked");
 setcheck(node,Pchecked);
 document.all.checked.value="";
 document.all.unchecked.value="";
 FindCheckedFromNode(TreeView1);
}
//讄子节炚w中
function setcheck(node,Pc)
{
 var i;
 var ChildNode=new Array();
 ChildNode=node.getChildren();
 
 if(parseInt(ChildNode.length)==0)
  return;
 else
 {
  for(i=0;i<ChildNode.length;i++)
  {
   var cNode;
   cNode=ChildNode[i];
   if(parseInt(cNode.getChildren().length)!=0)
    setcheck(cNode,Pc);
   cNode.setAttribute("Checked",Pc);
  }
 }
}
//获取所有节点状?br />function FindCheckedFromNode(node) {
 var i = 0;
 var nodes = new Array();
 nodes = node.getChildren();
 
 for (i = 0; i < nodes.length; i++) {
  var cNode;
  cNode=nodes[i];
  if (cNode.getAttribute("Checked"))
   AddChecked(cNode);
  else
      AddUnChecked(cNode);
  
  if (parseInt(cNode.getChildren().length) != 0 ) {
   FindCheckedFromNode(cNode);
  }
 }
}
//d选中节点
function AddChecked(node) {
 document.all.checked.value += node.getAttribute("NodeData");
 document.all.checked.value += ',';
}
//d未选中节点
function AddUnChecked(node) {
 document.all.unchecked.value += node.getAttribute("NodeData");
 document.all.unchecked.value += ',';
}
//-->
  </script>
 </HEAD>
 <body onload="initchecknode()">
  <iewc:TreeView id="TreeView1" runat="server" ExpandLevel="5">
   <iewc:TreeNode NodeData="0" CheckBox="True" Text="Node0" Expanded="True">
    <iewc:TreeNode NodeData="1" CheckBox="True" Text="Node1" Expanded="True"></iewc:TreeNode>
    <iewc:TreeNode NodeData="2" CheckBox="True" Text="Node2" Expanded="True">
     <iewc:TreeNode NodeData="3" CheckBox="True" Text="Node3" Expanded="True">
      <iewc:TreeNode NodeData="4" CheckBox="True" Text="Node4"

Expanded="True"></iewc:TreeNode>
     </iewc:TreeNode>
    </iewc:TreeNode>
   </iewc:TreeNode>
   <iewc:TreeNode NodeData="5" CheckBox="True" Text="Node5" Expanded="True">
    <iewc:TreeNode NodeData="6" CheckBox="True" Text="Node6" Expanded="True"></iewc:TreeNode>
   </iewc:TreeNode>
   <iewc:TreeNode NodeData="7" CheckBox="True" Text="Node7" Expanded="True">
    <iewc:TreeNode NodeData="8" CheckBox="True" Text="Node8" Expanded="True">
     <iewc:TreeNode NodeData="9" CheckBox="True" Text="Node9"

Expanded="True"></iewc:TreeNode>
    </iewc:TreeNode>
   </iewc:TreeNode>
  </iewc:TreeView><P>
   <TABLE id="Table1" cellSpacing="1" cellPadding="1" width="300" border="1">
    <TR>
     <TD>
      <asp:Label id="Label1" runat="server">checked</asp:Label></TD>
     <TD>
      <INPUT id="checked" type="text" size="32"></TD>
    </TR>
    <TR>
     <TD>
      <asp:Label id="Label2" runat="server">unchecked</asp:Label></TD>
     <TD><INPUT id="unchecked" type="text" size="32"></TD>
    </TR>
   </TABLE>
   <br>
  </P>
 </body>
</HTML>

 

W二个例子是关于如何在服务器端得到客L讄后的节点选中状?/p>

<%@ Register TagPrefix="iewc" Namespace="Microsoft.Web.UI.WebControls" Assembly="Microsoft.Web.UI.WebControls,

Version=1.0.2.226, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<HTML>
 <HEAD>
  <script language="C#" runat="server">
   private void Button1_Click(object sender, System.EventArgs e)
   {
    Response.Write(TreeView1.Nodes[0].Checked);
   }
  </script>
  <script language="javascript">
   function set_check()
   {
    var nodeindex = "0";
    var node=TreeView1.getTreeNode(nodeindex);
    node.setAttribute("Checked","True");
    TreeView1.queueEvent('oncheck', nodeindex);
   }
  </script>
 </HEAD>
 <body>
  <form id="TestTree" method="post" runat="server">
   <iewc:TreeView id="TreeView1" runat="server">
    <iewc:TreeNode CheckBox="True" Text="Node0"></iewc:TreeNode>
   </iewc:TreeView>
   <br>
   <input type="button" value="set check" onclick="set_check()">
   <br>
   <asp:Button id="Button1" runat="server" Text="submit" OnClick="Button1_Click"></asp:Button>
  </form>
 </body>
</HTML>

 



2006-12-12 00:05 发表评论
]]>
l典JavaScript代码(一)http://www.aygfsteel.com/zengke/articles/82594.htmlTue, 21 Nov 2006 11:48:00 GMThttp://www.aygfsteel.com/zengke/articles/82594.htmlhttp://www.aygfsteel.com/zengke/comments/82594.htmlhttp://www.aygfsteel.com/zengke/articles/82594.html#Feedback0http://www.aygfsteel.com/zengke/comments/commentRss/82594.htmlhttp://www.aygfsteel.com/zengke/services/trackbacks/82594.html阅读全文

2006-11-21 19:48 发表评论
]]>
JavaScript面向对象的支?/title><link>http://www.aygfsteel.com/zengke/articles/79906.html</link><dc:creator>曄</dc:creator><author>曄</author><pubDate>Wed, 08 Nov 2006 09:07:00 GMT</pubDate><guid>http://www.aygfsteel.com/zengke/articles/79906.html</guid><wfw:comment>http://www.aygfsteel.com/zengke/comments/79906.html</wfw:comment><comments>http://www.aygfsteel.com/zengke/articles/79906.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/zengke/comments/commentRss/79906.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/zengke/services/trackbacks/79906.html</trackback:ping><description><![CDATA[ <font size="2">JavaScript面向对象的支?br />~~~~~~~~~~~~~~~~~~<br />很少有h对JavaScript的面向对象特性进行系l的分析。我希望接下来的文字让你了解到这<br />个语a最ؓ人知的一面?br /><br />1. JavaScript中的cd<br />--------<br />虽然JavaScript是一个基于对象的语言Q但对象(Object)在JavaScript中不是第一型的。JS<br />是以函数(Function)为第一型的语言。这栯Q不但是因ؓJS中的函数h高语言中的?br />数的各种Ҏ,而且也因为在JS中,Object也是由函数来实现的。——关于这一点,可以?br />后文中“构造与析构”部分看到更q一步的说明?br /><br />JS中是q型的Q他的内|类型简单而且清晰Q?br />---------------------------------------------------------<br />undefined : 未定?br />number    : 数字<br />boolean   : 布尔?br />string    : 字符?br />function  : 函数<br />object    : 对象<br /><br /> 1). undefinedcd<br />========================<br />在IE5及以下版本中Q除了直接赋值和typeof()之外Q其它Q何对undefined的操作都导?br />异常。如果需要知道一个变量是否是undefinedQ只能采用typeof()的方法:<br /><script><br />var v;<br />if (typeof(v) == 'undefined') {<br />  // ...<br />}<br /></script><br /><br />但是在IE5.5及以上版本中Qundefined是一个已实现的系l保留字。因此可以用undefined?br />比较和运。检一个值是否是undefined的更单方法可以是Q?br /><script><br />var v;<br />if (v === undefined) {<br />  // ...<br />}<br /></script><br /><br />因此Z使得核心代码?部分?兼容IE5及早期版本,Romo核心单元中有一行代码用?br />“声明”一个undefined|<br />//---------------------------------------------------------<br />// code from Qomolangma, in JSEnhance.js<br />//---------------------------------------------------------<br />var undefined = void null;<br /><br />q一行代码还有一Ҏ需要说明的Q就是void语句的应用。void表明“执行其后的语句Q且<br />忽略q回值”。因此在void之后可以出现能被执行的Q何“单个”语句。而执行的l果是<br />undefined。当Ӟ如果你愿意,你也可以用下面的代码之一“定义undefined”?br />//---------------------------------------------------------<br />// 1. 较复杂的ҎQ利用一个匿名的I函数执行的q回<br />//---------------------------------------------------------<br />var undefined = function(){}();<br /><br />//---------------------------------------------------------<br />// 2. 代码更简z,但不易懂的方?br />//---------------------------------------------------------<br />var undefined = void 0;<br /><br />void也能像函C样用,因此void(0)也是合法的。有些时候,一些复杂的语句可能不能<br />使用void的关键字形式Q而必要使用void的函数Ş式。例如:<br />//---------------------------------------------------------<br />// 必须使用void()形式的复杂表辑ּ<br />//---------------------------------------------------------<br />void(i=1);       // 或如下语?<br />void(i=1, i++);<br /><br /> 2). numbercd<br />========================<br />JavaScript中L处理点敎ͼ因此它没有象Delphi中的MaxIntq样的常量,反而是有这<br />样两个常值定义:<br />  Number.MAX_VALUE  : q回 JScript 能表辄最大的数。约{于 1.79E+308?br />  Number.MIN_VALUE  : q回 JScript 最接近0的数。约{于 2.22E-308?br /><br />因ؓ没有整型的缘故,因此在一些关于CSS和DOM属性的q算中,如果你期望取gؓ整数2Q?br />你可能会得到字符东y?.0”——或者类g此的一些情c这U情况下Q你可能需要用<br />到全局对象(Gobal)的parseInt()Ҏ?br /><br />全局对象(Gobal)中还有两个属性与numbercd的运有养I<br />  NaN      : 术表达式的q算l果不是数字Q则q回NaN倹{?br />  Infinity : 比MAX_VALUE更大的数?br /><br />如果一个值是NaNQ那么他可以通过全局对象(Gobal)的isNaN()Ҏ来检。然而两个NaN<br />g间不是互{的。如下例Q?br />//---------------------------------------------------------<br />// NaN的运与?br />//---------------------------------------------------------<br />var<br />  v1 = 10 * 'a';<br />  v2 = 10 * 'a';<br />document.writeln(isNaN(v1));<br />document.writeln(isNaN(v2));<br />document.writeln(v1 == v2);<br /><br />全局对象(Gobal)的Infinity表示比最大的敊W?Number.MAX_VALUE) 更大的倹{在JS中,<br />它在数学q算时的价g正无Ih一L。——在一些实用技巧中Q它也可以用来做一<br />个数l序列的边界?br /><br />Infinity在Number对象中被定义为POSITIVE_INFINITY。此外,负无I也在Number中被?br />义:<br />  Number.POSITIVE_INFINITY  : 比最大正敎ͼNumber.MAX_VALUEQ更大的倹{正无穷?br />  Number.NEGATIVE_INFINITY  : 比最负敎ͼ-Number.MAX_VALUEQ更的倹{负无穷?br /><br />与NaN不同的是Q两个Infinity(?Infinity)之间是互{的。如下例Q?br />//---------------------------------------------------------<br />// Infinity的运与?br />//---------------------------------------------------------<br />var<br />  v1 = Number.MAX_VALUE * 2;<br />  v2 = Number.MAX_VALUE * 3;<br />document.writeln(v1);<br />document.writeln(v2);<br />document.writeln(v1 == v2);<br /><br />在Global中其它与numbercd相关的方法有Q?br /> isFinite()   : 如果值是NaN/正无I?负无IPq回falseQ否则返回true?br /> parseFloat() : 从字W串(的前~部分)取一个QҎ。不成功则返回NaN?br /><br /> 3). booleancd<br />========================<br /> (?<br /><br /> 4). stringcd<br />========================<br />JavaScript中的Stringcd原本没有什么特D的Q但是JavaScriptZ适应<br />“浏览器实现的超文本环境”,因此它具有一些奇怪的Ҏ。例如:<br />  link() : 把一个有HREF属性的链接标{?lt;A>攑֜String对象中的文本两端?br />  big()  : 把一?lt;big>标签攑֜String对象中的文本两端?br />以下Ҏ与此cdQ?br />  anchor()<br />  blink()<br />  bold()<br />  fixed()<br />  fontcolor()<br />  fontsize()<br />  italics()<br />  small()<br />  strike()<br />  sub()<br />  sup()<br /><br />除此之外Qstring的主要复杂性来自于在JavaScript中无所不在的toString()<br />Ҏ。这也是JavaScript为浏览器环境而提供的一个很重要的方法。例如我?br />声明一个对象,但是要用document.writeln()来输出它Q在IE中会昄什么呢Q?br /><br />下例说明q个问题Q?br />//---------------------------------------------------------<br />// toString()的应?br />//---------------------------------------------------------<br />var<br />  s = new Object();<br /><br />s.v1 = 'hi,';<br />s.v2 = 'test!';<br />document.writeln(s);<br />document.writeln(s.toString());<br /><br />s.toString = function() {<br />  return s.v1 + s.v2;<br />}<br />document.writeln(s);<br /><br />在这个例子中Q我们看刎ͼ当一个对象没有重新声?覆盖)自己toString()?br />法的时候,那么它作为字W串型态用时(例如被writeln)Q就会调用Java Script<br />环境~省的toString()。反q来Q你也可以重新定义JavaScript理解q个对象<br />的方法?br /><br />很多JavaScript框架Q在实现“模李쀝机制的时候,利用了q个Ҏ。例?br />他们用这样定义一个FontElement对象Q?br />//---------------------------------------------------------<br />// 利用toString()实现模板机制的简单原?br />//---------------------------------------------------------<br />function FontElement(innerHTML) {<br />  this.face = '宋体';<br />  this.color = 'red';<br />  // more...<br /><br />  var ctx = innerHTML;<br />  this.toString = function() {<br />    return '<Font FACE="' + this.face + '" COLOR="' + this.color + '">'<br />      + ctx<br />      + '</FONT>';<br />  }<br />}<br /><br />var obj = new FontElement('q是一个测试?);<br /><br />// 留意下面q行代码的写?br />document.writeln(obj);<br /><br /> 5). functioncd<br />========================<br />javascript函数h很多Ҏ,除了面向对象的部分之?q在后面讲述)Q它?br />已的一些独特特性应用也很广泛?br /><br />首先javascript中的每个函数Q在调用q程中可以执有一个arguments对象。这?br />对象是由脚本解释环境创徏的,你没有别的方法来自己创徏一个arguments对象?br /><br />arguments可以看成一个数l:它有length属性,q可以通过arguments[n]的方?br />来访问每一个参数。然而它最重要的,却是可以通过 callee 属性来得到正在执行<br />的函数对象的引用?br /><br />接下的问题变得很有趣QFunction对象有一个 caller 属性,指向正在调用当前<br />函数的父函数对象的引用?br /><br />——我们已l看刎ͼ我们可以在JavaScript里面Q通过callee/caller来遍历执?br />期的调用栈。由于arguments事实上也是Function的一个属性,因此我们事实上也<br />能遍历执行期调用栈上的每一个函数的参数。下面的代码是一个简单的CZQ?br /><br />//---------------------------------------------------------<br />// 调用栈的遍历<br />//---------------------------------------------------------<br />function foo1(v1, v2) {<br />  foo2(v1 * 100);<br />}<br /><br />function foo2(v1) {<br />  foo3(v1 * 200);<br />}<br /><br />function foo3(v1) {<br />  var foo = arguments.callee;<br />  while (foo && (foo != window)) {<br />    document.writeln('调用参数Q?lt;br>', '---------------<br>');<br /><br />    var args = foo.arguments, argn = args.length;<br />    for (var i=0; i<argn; i++) {<br />      document.writeln('args[', i, ']: ', args[i], '<br>');<br />    }<br />    document.writeln('<br>');<br /><br />    // 上一U?br />    foo = foo.caller;<br />  }<br />}<br /><br />// q行试<br />foo1(1, 2);<br /><br />2. JavaScript面向对象的支?br />--------<br />在前面的例子中其实已l讲Cobjectcd的“类型声明”与“实例创建”?br />在JavaScript中,我们需要通过一个函数来声明自己的objectcdQ?br />//---------------------------------------------------------<br />// JavaScript中对象的cd声明的Ş式代?br />// (以后的文档中Q“对象名”通常用MyObject来替?<br />//---------------------------------------------------------<br />function 对象?参数? {<br />  this.属性? 初始?<br /><br />  this.Ҏ = function(Ҏ参数? {<br />    // Ҏ实现代码<br />  }<br />}<br /><br />然后Q我们可以通过q样的代码来创徏q个对象cd的一个实例:<br />//---------------------------------------------------------<br />// 创徏实例的Ş式代?br />// (以后的文中Q“实例变量名”通常用obj来替?<br />//---------------------------------------------------------<br />var 实例变量名? new 对象?参数?;<br /><br />接下来我们来看“对象”在JavaScript中的一些具体实现和奇怪特性?br /><br /> 1). 函数在JavaScript的面向对象机制中的五重n?br /> ------<br />“对象名”——如MyObject()——这个函数充当了以下语言角色Q?br />  (1) 普通函?br />  (2) cd声明<br />  (3) cd的实?br />  (4) cd?br />  (5) 对象的构造函?br /><br />一些程序员(例如DelphiE序?习惯于类型声明与实现分开。例如在delphi<br />中,Interface节用于声明类型或者变量,而implementation节用于书写类?br />的实C码,或者一些用于执行的函数、代码流E?br /><br />但在JavaScript中,cd的声明与实现是؜在一L。一个对象的cd(c?<br />通过函数来声明,this.xxxx表明了该对象可具有的属性或者方法?br /><br />q个函数的同时也是“类引用”。在JavaScriptQ如果你需要识别一个对?br />的具体型别,你需要执有一个“类引用”。——当Ӟ也就是这个函数的?br />字。instanceof q算W就用于识别实例的类型,我们来看一下它的应用:<br />//---------------------------------------------------------<br />// JavaScript中对象的cd识别<br />//   语法:  对象实例 instanceof cd?br />//---------------------------------------------------------<br />function MyObject() {<br />  this.data = 'test data';<br />}<br /><br />// q里MyObject()作ؓ构造函C?br />var obj = new MyObject();<br />var arr = new Array();<br /><br />// q里MyObject作ؓcd用?br />document.writeln(obj instanceof MyObject);<br />document.writeln(arr instanceof MyObject);<br /><br />================<br />(未完待箋)<br />================<br />接下来的内容Q?br /><br />2. JavaScript面向对象的支?br />--------<br /><br /> 2). 反射机制在JavaScript中的实现<br /> 3). this与with关键字的使用<br /> 4). 使用in关键字的q算<br /> 5). 使用instanceof关键字的q算<br /> 6). 其它与面向对象相关的关键?br /><br />3. 构造与析构<br /><br />4. 实例和实例引?br /><br />5. 原型问题<br /><br />6. 函数的上下文环境<br /><br />7. 对象的类型检查问?br /><br />2). 反射机制在JavaScript中的实现<br /> ------<br />  JavaScript中通过for..in语法来实C反射机制。但是JavaScript中ƈ?br />明确区分“属性”与“方法”,以及“事件”。因此,对属性的cd考查在JS<br />中是个问题。下面的代码单示例for..in的用与属性识别:<br />//---------------------------------------------------------<br />// JavaScript中for..in的用和属性识?br />//---------------------------------------------------------<br />var _r_event = _r_event = /^[Oo]n.*/;<br />var colorSetting = {<br />  method: 'red',<br />  event: 'blue',<br />  property: ''<br />}<br /><br />var obj2 = {<br />  a_method : function() {},<br />  a_property: 1,<br />  onclick: undefined<br />}<br /><br />function propertyKind(obj, p) {<br />  return  (_r_event.test(p) && (obj[p]==undefined || typeof(obj[p])=='function')) ? 'event'<br />    : (typeof(obj[p])=='function') ? 'method'<br />    : 'property';<br />}<br /><br />var objectArr = ['window', 'obj2'];<br /><br />for (var i=0; i<objectArr.length; i++) {<br />  document.writeln('<p>for ', objectArr[i], '<hr>');<br /><br />  var obj = eval(objectArr[i]);<br />  for (var p in obj) {<br />    var kind = propertyKind(obj, p);<br />    document.writeln('obj.', p, ' is a ', kind.fontcolor(colorSetting[kind]), ': ', obj[p], '<br>');<br />  }<br /><br />  document.writeln('</p>');<br />}<br /><br />一个常常被开发者忽略的事实是:JavaScript本n是没有事?Event)pȝ的。?br />常我们在JavaScript用到的onclick{事Ӟ其实是IE的DOM模型提供的。从更内?br />的角度上ԌIE通过COM的接口属性公布了一l事件接口给DOM?br /><br />有两个原因,使得在JS中不能很好的识别“一个属性是不是事g”:<br />  - COM接口中本w只有方法,属性与事gQ都是通过一lget/setҎ来公布的?br />  - JavaScript中,本nq没有独立的“事件”机制?br /><br />因此我们看到event的识别方法,是检属性名是否是以'on'字符串开??On'开<br />头的是Qomo的约?。接下来Q由于DOM对象中的事g是可以不指定处理函数的,q?br />U情况下事g句柄为null?Qomo采用相同的约?Q在另外的一些情况下Q用户可<br />能象obj2q样Q定义一个gؓ undefined的事件。因此“事件”的判定条g被处?br />成一个复杂的表达式:<br />   ("属性以on/On开? && ("gؓnull/undefined" || "cd为function"))<br /><br />另外Q从上面的这D代码的q行l果来看。对DOM对象使用for..inQ是不能列D?br />对象Ҏ来的?br /><br />最后说明一炏V事实上Q在很多语言的实CQ“事件”都不是“面向对象”的?br />aҎ,而是由具体的~程模型来提供的。例如Delphi中的事g驱动机制Q是由Win32<br />操作pȝ中的H口消息机制来提供,或者由用户代码在Component/Class中主动调?br />事g处理函数来实现?br /><br />“事件”是一个“如何驱动编E模型”的机制Q问题,而不是语a本n的问题。然<br />而以PME(property/method/event)为框架的OOP概念Q已l深入h心,所以当~程?br />a或系l表现出q些Ҏ来的时候,已l没人关心“eventI竟是谁实现”的了?br /><br /> 3). this与with关键字的使用<br /> ------<br /> 在JavaScript的对象系l中Qthis关键字用在两U地方:<br />   - 在构造器函数中,指代新创建的对象实例<br />   - 在对象的Ҏ被调用时Q指代调用该Ҏ的对象实?br /><br /> 如果一个函数被作ؓ普通函?而不是对象方?调用Q那么在函数中的this关键?br />指向window对象。与此相同的Q如果this关键字不在Q何函CQ那么他也指?br />window对象?br /><br /> ׃在JavaScript中不明确区分函数与方法。因此有些代码看h很奇怪:<br />//---------------------------------------------------------<br />// 函数的几U可能调用Ş?br />//---------------------------------------------------------<br />function foo() {<br />  // 下面的this指代调用该方法的对象实例<br />  if (this===window) {<br />    document.write('call a function.', '<BR>');<br />  }<br />  else {<br />    document.write('call a method, by object: ', this.name, '<BR>');<br />  }<br />}<br /><br />function MyObject(name) {<br />  // 下面的this指代new关键字新创徏实例<br />  this.name = name;<br />  this.foo = foo;<br />}<br /><br />var obj1 = new MyObject('obj1');<br />var obj2 = new MyObject('obj2');<br /><br />// 试1: 作ؓ函数调用<br />foo();<br /><br />// 试2: 作ؓ对象Ҏ的调?br />obj1.foo();<br />obj2.foo();<br /><br />// 试3: 函C为“指定对象的”方法调?br />foo.call(obj1);<br />foo.apply(obj2);<br /><br />在上面的代码里,obj1/obj2对foo()的调用是很普通的调用Ҏ。——也?br />是在构造器上,一个函数指定ؓ对象的方法?br /><br />而测?中的call()与apply()比较特D?br /><br />在这个测试中Qfoo()仍然作ؓ普通函数来调用Q只是JavaScript的语aҎ?br />允许在call()/apply()Ӟ传入一个对象实例来指定foo()的上下文环境中所<br />出现的this关键字的引用。——需要注意的是,此时的foo()仍旧是一个普?br />函数调用Q而不是对象方法调用?br /><br />与this“指C用该Ҏ的对象实例”有些类同的Qwith()语法也用于限?br />“在一D代码片D中默认使用对象实例”。——如果不使用with()语法Q那<br />么这D代码将受到更外层with()语句的媄响;如果没有更外层的with()Q那<br />么这D代码的“默认用的对象实例”将是window?br /><br />然而需要注意的是this与with关键字不是互为媄响的。如下面的代码:<br />//---------------------------------------------------------<br />// 试: this与with关键字不是互为媄响的<br />//---------------------------------------------------------<br />function test() {<br />  with (obj2) {<br />    this.value = 8;<br />  }<br />}<br />var obj2 = new Object();<br />obj2.value = 10;<br /><br />test();<br />document.writeln('obj2.value: ', obj2.value, '<br>');<br />document.writeln('window.value: ', window.value, '<br>');<br /><br />你不能指望这L代码在调用结束后Q会使obj2.value属性置gؓ8。这几行<br />代码的结果是Qwindow对象多了一个value属性,q且gؓ8?br /><br />with(obj){...}q个语法Q只能限定对obj的既有属性的dQ而不能主动的<br />声明它。一旦with()里的对象没有指定的属性,或者with()限定了一个不是对<br />象的数据Q那么结果会产生一个异常?br /><br /> 4). 使用in关键字的q算<br /> ------<br /> 除了用for..in来反对象的成员信息之外QJavaScript中也允许直接用in<br />关键字去对象是否有指定名字的属性?br /><br /> in关键字经常被提及的原因ƈ不是它检属性是否存在的能力Q因此在早期<br />的代码中Q很多可喜欢用“if (!obj.propName) {}” 这L方式来检propName<br />是否是有效的属性。——很多时候,有效性比“是否存有该属性”更<br />有实用性。因此这U情况下Qin只是一个可选的、官方的Ҏ?br /><br /> in关键字的重要应用是高速字W串索。尤其是在只需要判定“字W串是否<br />存在”的情况下。例?0万个字符Ԍ如果存储在数l中Q那么检索效率将?br />极差?br />//---------------------------------------------------------<br />// 使用对象来检?br />//---------------------------------------------------------<br />function arrayToObject(arr) {<br />  for (var obj=new Object(), i=0, imax=arr.length; i<imax; i++) {<br />    obj[arr[i]]=null;<br />  }<br />  return obj;<br />}<br /><br />var<br />  arr = ['abc', 'def', 'ghi']; // more and more...<br />  obj = arrayToObject(arr);<br /><br />function valueInArray(v) {<br />  for (var i=0, imax=arr.length; i<imax; i++) {<br />    if (arr[i]==v) return true;<br />  }<br /><br />  return false;<br />}<br /><br />function valueInObject(v) {<br />  return v in obj;<br />}<br /><br />q种使用关键字in的方法,也存在一些限制。例如只能查扑֭W串Q而数<br />l元素可以是L倹{另外,arrayToObject()也存在一些开销Q这使得?br />不适合于频J变动的查找集。最后,(我想你可能已l注意到?使用对象<br />来查扄时候ƈ不能准确定位到查找数据,而数l中可以指向l果的下标?br /><br />八、JavaScript面向对象的支?br />~~~~~~~~~~~~~~~~~~<br />(l?<br /><br />2. JavaScript面向对象的支?br />--------<br />(l?<br /><br /> 5). 使用instanceof关键字的q算<br /> ------<br /> 在JavaScript中提供了instanceof关键字来实例的cd。这在前面讨<br />论它的“五重n份”时已经讲过。但instanceof的问题是Q它L列D整个<br />原型链以类?关于原型l承的原理在“构造与析构”小节讲q?Q如Q?br />//---------------------------------------------------------<br />// instanceof使用中的问题<br />//---------------------------------------------------------<br />function MyObject() {<br />  // ...<br />}<br /><br />function MyObject2() {<br />  // ...<br />}<br />MyObject2.prototype = new MyObject();<br /><br />obj1 = new MyObject();<br />obj2 = new MyObject2();<br /><br />document.writeln(obj1 instanceof MyObject, '<BR>');<br />document.writeln(obj2 instanceof MyObject, '<BR>');<br /><br />我们看到Qobj1与obj2都是MyObject的实例,但他们是不同的构造函C?br />的。——注意,q在面向对象理论中正的Q因为obj2是MyObject的子cd<br />例,因此它具有与obj1相同的特性。在应用中这是obj2的多态性的体现之一?br /><br />但是Q即便如此,我们也必面临这L问题Q如何知道obj2与obj1是否?br />相同cd的实例呢Q——也是_q构造器都相同?<br /><br />instanceof关键字不提供q样的机制。一个提供实现这U检的能力的,?br />Object.constructor属性。——但请先CQ它的用远比你惌的要难?br /><br />好的Q问题先到这里。constructor属性已l涉及到“构造与析构”的问题Q?br />q个我们后面再讲。“原型扎쀝、“构造与析构”是JavaScript的OOP?br />的主要问题、核心问题,以及“致命问题”?br /><br /> 6). null与undefined<br /> ------<br /> 在JavaScript中,null与undefined曾一度我迷惑。下面的文字Q有利于<br />你更清晰的认知它(或者让你更qh)Q?br />   - null是关键字Qundefined是Global对象的一个属性?br />   - null是对?I对? 没有M属性和Ҏ)Qundefined是undefinedc?br />     型的倹{试试下面的代码Q?br />       document.writeln(typeof null);<br />       document.writeln(typeof undefined);<br />   - 对象模型中,所有的对象都是Object或其子类的实例,但null对象例外Q?br />       document.writeln(null instanceof Object);<br />   - null“等?==)”于undefinedQ但不“全{?===)”于undefinedQ?br />       document.writeln(null == undefined);<br />       document.writeln(null == undefined);<br />   - q算时null与undefined都可以被cd转换为falseQ但不等gfalseQ?br />       document.writeln(!null, !undefined);<br />       document.writeln(null==false);<br />       document.writeln(undefined==false);<br /><br />八、JavaScript面向对象的支?br />~~~~~~~~~~~~~~~~~~<br />(l?<br /><br />3. 构造、析构与原型问题<br />--------<br /> 我们已经知道一个对象是需要通过构造器函数来生的。我们先C几点Q?br />   - 构造器是一个普通的函数<br />   - 原型是一个对象实?br />   - 构造器有原型属性,对象实例没有<br />   - (如果正常地实现承模型,)对象实例的constructor属性指向构造器<br />   - 从三、四条推出:obj.constructor.prototype指向该对象的原型<br /><br /> 好,我们接下来分析一个例子,来说明JavaScript的“承原型”声明,?br />及构造过E?br />//---------------------------------------------------------<br />// 理解原型、构造、承的CZ<br />//---------------------------------------------------------<br />function MyObject() {<br />  this.v1 = 'abc';<br />}<br /><br />function MyObject2() {<br />  this.v2 = 'def';<br />}<br />MyObject2.prototype = new MyObject();<br /><br />var obj1 = new MyObject();<br />var obj2 = new MyObject2();<br /><br /> 1). new()关键字的形式化代?br /> ------<br /> 我们先来看“obj1 = new MyObject()”这行代码中的这个new关键字?br /><br />new关键字用于生一个新的实例(说到q里补充一下,我习惯于把保留字叫关?br />字。另外,在JavaScript中new关键字同时也是一个运符Q,q个实例的缺省属?br />中,(臛_)会执有构造器函数的原型属?prototype)的一个引?在ECMA Javascript<br />规范中,对象的这个属性名定义为__proto__)?br /><br />每一个函敎ͼ无论它是否用作构造器Q都会有一个独一无二的原型对?prototype)?br />对于JavaScript“内|对象的构造器”来_它指向内部的一个原型。缺省时JavaScript<br />构造出一个“空的初始对象实?不是null)”ƈ使原型引用指向它。然而如果你l函<br />数的q个prototype赋一个新的对象,那么新的对象实例执有它的一个引用?br /><br />接下来,构造过E将调用MyObject()来完成初始化。——注意,q里只是“初?br />化”?br /><br />Z清楚地解释这个过E,我用代码形式化地描述一下这个过E:<br />//---------------------------------------------------------<br />// new()关键字的形式化代?br />//---------------------------------------------------------<br />function new(aFunction) {<br />  // 基本对象实例<br />  var _this = {};<br /><br />  // 原型引用<br />  var _proto= aFunction.prototype;<br /><br />/* if compat ECMA Script<br />  _this.__proto__ = _proto;<br />*/<br /><br />  // 为存取原型中的属性添?内部?getter<br />  _this._js_GetAttributes= function(name) {<br />    if (_existAttribute.call(this, name))<br />      return this[name]<br />    else if (_js_LookupProperty.call(_proto, name))<br />      retrun OBJ_GET_ATTRIBUTES.call(_proto, name)<br />    else<br />      return undefined;<br />  }<br /><br />  // 为存取原型中的属性添?内部?setter<br />  _this._js_GetAttributes = function(name, value) {<br />    if (_existAttribute.call(this, name)) <br />      this[name] = value<br />    else if (OBJ_GET_ATTRIBUTES.call(_proto, name) !== value) {<br />      this[name] = value    // 创徏当前实例的新成员<br />    }<br />  }<br /><br />  // 调用构造函数完成初始化, (如果?)传入args<br />  aFunction.call(_this);<br /><br />  // q回对象<br />  return _this;<br />}<br /><br />所以我们看C下两点:<br />  - 构造函?aFunction)本n只是对传入的this实例做“初始化”处理,?br />    不是构造一个对象实例?br />  - 构造的q程实际发生在new()关键?q算W的内部?br /><br />而且Q构造函?aFunction)本nq不需要操作prototypeQ也不需要回传this?br /><br /> 2). q户代码维护的原型(prototype)?br /> ------<br /> 接下来我们更深入的讨论原型链与构造过E的问题。这是Q?br />  - 原型链是用户代码创徏的,new()关键字ƈ不协助维护原型链<br /><br />以Delphi代码ZQ我们在声明l承关系的时候,可以用这L代码Q?br />//---------------------------------------------------------<br />// delphi中用的“类”类型声?br />//---------------------------------------------------------<br />type<br />  TAnimal = class(TObject); // 动物<br />  TMammal = class(TAnimal); // Z^动物<br />  TCanine = class(TMammal); // 犬科的哺乛_?br />  TDog = class(TCanine);    // ?br /><br />q时QDelphi的编译器会通过~译技术来l护一个承关p链表。我们可以?br />q类g下的代码来查询这个链表:<br />//---------------------------------------------------------<br />// delphi中用关系链表的关键代?br />//---------------------------------------------------------<br />function isAnimal(obj: TObject): boolean;<br />begin<br />  Result := obj is TAnimal;<br />end;<br /><br />var<br />  dog := TDog;<br /><br />// ...<br />dog := TDog.Create();<br />writeln(isAnimal(dog));<br /><br />可以看到Q在Delphi的用户代码中Q不需要直接护承关pȝ链表。这是因<br />为Delphi是强cd语言Q在处理用class()关键字声明类型时Qdelphi的编译器<br />已经为用h造了q个l承关系链。——注意,q个q程是声明,而不是执?br />代码?br /><br />而在JavaScript中,如果需要获知对象“是否是某个基类的子cd象”,那么<br />你需要手工的来维?与delphiq个例子cM?一个链表。当Ӟq个链表?br />叫类型承树Q而叫?对象?原型链表”。——在JS中,没有“类”类型?br /><br />参考前面的JS和Delphi代码Q一个类同的例子是这P<br />//---------------------------------------------------------<br />// JS中“原型链表”的关键代码<br />//---------------------------------------------------------<br />// 1. 构造器<br />function Animal() {};<br />function Mammal() {};<br />function Canine() {};<br />function Dog() {};<br /><br />// 2. 原型链表<br />Mammal.prototype = new Animal();<br />Canine.prototype = new Mammal();<br />Dog.prototype = new Canine();<br /><br />// 3. CZ函数<br />function isAnimal(obj) {<br />  return obj instanceof Animal;<br />}<br /><br />var<br />  dog = new Dog();<br />document.writeln(isAnimal(dog));<br /><br />可以看到Q在JS的用户代码中Q“原型链表”的构徏Ҏ是一行代码:<br />  "当前cȝ构造器函数".prototype = "直接父类的实?<br /><br />q与Delphi一cȝ语言不同Q维护原型链的实质是在执行代码,而非声明?br /><br />那么Q“是执行而非声明”到底有什么意义呢Q?br /><br />JavaScript是会有编译过E的。这个过E主要处理的是“语法检错”、“语<br />法声明”和“条件编译指令”。而这里的“语法声明”,主要处理的就是函<br />数声明。——这也是我说“函数是W一cȝQ而对象不是”的一个原因?br /><br />如下例:<br />//---------------------------------------------------------<br />// 函数声明与执行语句的关系(firefox 兼容)<br />//---------------------------------------------------------<br />// 1. 输出1234<br />testFoo(1234);<br /><br />// 2. 试输出obj1<br />// 3. 试输出obj2<br />testFoo(obj1);<br />try {<br />  testFoo(obj2);<br />}<br />catch(e) {<br />  document.writeln('Exception: ', e.description, '<BR>');<br />}<br /><br />// 声明testFoo()<br />function testFoo(v) {<br />  document.writeln(v, '<BR>');<br />}<br /><br />//  声明object<br />var obj1 = {};<br />obj2 = {<br />  toString: function() {return 'hi, object.'}<br />}<br /><br />// 4. 输出obj1<br />// 5. 输出obj2<br />testFoo(obj1);<br />testFoo(obj2);<br /><br />q个CZ代码在JS环境中执行的l果是:<br />------------------------------------<br />  1234<br />  undefined<br />  Exception: 'obj2' 未定?br />  [object Object]<br />  hi, obj<br />------------------------------------<br />问题是,testFoo()是在它被声明之前被执行的Q而同L“直接声明”的<br />形式定义的object变量Q却不能在声明之前引用。——例子中Q第二、三<br />个输入是不正的?br /><br />函数可以在声明之前引用,而其它类型的数值必d声明之后才能被用?br />q说明“声明”与“执行期引用”在JavaScript中是两个q程?br /><br />另外我们也可以发玎ͼ使用"var"来声明的时候,~译器会先确认有该变?br />存在Q但变量的g是“undefined”。——因此“testFoo(obj1)”不会发<br />生异常。但是,只有{到关于obj1的赋D句被执行q,才会有正常的输出?br />请对照第二、三与第四、五行输出的差异?br /><br />׃JavaScript对原型链的维护是“执行”而不是“声明”,q说明“原?br />链是q户代码来l护的,而不是编译器l护的?br /><br />p个推论,我们来看下面q个例子Q?br />//---------------------------------------------------------<br />// CZQ错误的原型?br />//---------------------------------------------------------<br />// 1. 构造器<br />function Animal() {}; // 动物<br />function Mammal() {}; // Z^动物<br />function Canine() {}; // 犬科的哺乛_?br /><br />// 2. 构造原型链<br />var instance = new Mammal();<br />Mammal.prototype = new Animal();<br />Canine.prototype = instance;<br /><br />// 3. 试输出<br />var obj = new Canine();<br />document.writeln(obj instanceof Animal);<br /><br />q个输出l果Q我们看到一个错误的原型铑֯致的l果“犬U的Z^?br />物‘不是’一U动物”?br /><br />Ҏ在于?. 构造原型链”下面的几行代码是解释执行的Q而不是象var?br />function那样是“声明”ƈ在编译期被理解的。解决问题的Ҏ是修攚w?br />行代码,使得它的“执行过E”符合逻辑Q?br />//---------------------------------------------------------<br />// 上例的修正代?部分)<br />//---------------------------------------------------------<br />// 2. 构造原型链<br />Mammal.prototype = new Animal();<br />var instance = new Mammal();<br />Canine.prototype = instance;<br /><br /> 3). 原型实例是如何被构造过E用的<br /> ------<br /> 仍以DelphiZ。构造过E中Qdelphi中会首先创徏一个指定实例大的<br />“空的对象”,然后逐一l属性赋|以及调用构造过E中的方法、触发事<br />件等?br /><br />JavaScript中的new()关键字中隐含的构造过E,与Delphi的构造过Eƈ不完全一致。但<br />在构造器函数中发生的行ؓ却与上述的类|<br />//---------------------------------------------------------<br />// JS中的构造过E?形式代码)<br />//---------------------------------------------------------<br />function MyObject2() {<br />  this.prop = 3;<br />  this.method = a_method_function;<br /><br />  if (you_want) {<br />    this.method();<br />    this.fire_OnCreate();<br />  }<br />}<br />MyObject2.prototype = new MyObject(); // MyObject()的声明略<br /><br />var obj = new MyObject2();<br /><br />如果以单个类为参考对象的Q这个构造过E中JavaScript可以拥有与Delphi<br />一样丰富的行ؓ。然而,׃Delphi中的构造过E是“动态的”,因此事实?br />Delphiq会调用父类(MyObject)的构造过E,以及触发父类的OnCreate()事g?br /><br />JavaScript没有q样的特性。父cȝ构造过E仅仅发生在为原?prototype<br />属?赋值的那一行代码上。其后,无论有多个new MyObject2()发生Q?br />MyObject()q个构造器都不会被使用。——这也意味着Q?br />  - 构造过E中Q原型对象是一ơ性生成的Q新对象只持有这个原型实例的引用<br />    (q用“写复制”的机制来存取其属?Q而ƈ不再调用原型的构造器?br /><br />׃不再调用父类的构造器Q因此Delphi中的一些特性无法在JavaScript中实现?br />q主要媄响到构造阶D늚一些事件和行ؓ。——无法把一些“对象构造过E中?br />的代码写到父cȝ构造器中。因为无论子cL造多次Q这ơ对象的构造过E根<br />本不会激zȝcL造器中的代码?br /><br />JavaScript中属性的存取是动态的Q因为对象存取父cd性依赖于原型链表Q构?br />q程却是静态的Qƈ不访问父cȝ构造器Q而在Delphi{一些编译型语言中,(不<br />用读写器?属性的存取是静态的Q而对象的构造过E则动态地调用父类的构造函数?br />所以再一ơ请大家看清楚new()关键字的形式代码中的q一行:<br />//---------------------------------------------------------<br />// new()关键字的形式化代?br />//---------------------------------------------------------<br />function new(aFunction) {<br />  // 原型引用<br />  var _proto= aFunction.prototype;<br /><br />  // ...<br />}<br /><br />q个q程中,JavaScript做的是“get a prototype_Ref”,而Delphi{其它语a?br />的是“Inherited Create()”?br /><br />八、JavaScript面向对象的支?br />~~~~~~~~~~~~~~~~~~<br />(l?<br /><br /> 4). 需要用L护的另一个属性:constructor<br /> ------<br /> 回顾前面的内容,我们提到q:<br />   - (如果正常地实现承模型,)对象实例的constructor属性指向构造器<br />   - obj.constructor.prototype指向该对象的原型<br />   - 通过Object.constructor属性,可以obj2与obj1是否是相同类型的实例<br /><br />  与原型链要通过用户代码来维护prototype属性一P实例的构造器属性constructor<br />也需要用户代码维护?br /><br />  对于JavaScript的内|对象来_constructor属性指向内|的构造器函数。如Q?br />//---------------------------------------------------------<br />// 内置对象实例的constructor属?br />//---------------------------------------------------------<br />var _object_types = {<br />  'function'  : Function,<br />  'boolean'   : Boolean,<br />  'regexp'    : RegExp,<br />// 'math'     : Math,<br />// 'debug'    : Debug,<br />// 'image'    : Image;<br />// 'undef'    : undefined,<br />// 'dom'      : undefined,<br />// 'activex'  : undefined,<br />  'vbarray'   : VBArray,<br />  'array'     : Array,<br />  'string'    : String,<br />  'date'      : Date,<br />  'error'     : Error,<br />  'enumerator': Enumerator,<br />  'number'    : Number,<br />  'object'    : Object<br />}<br /><br />function objectTypes(obj) {<br />  if (typeof obj !== 'object') return typeof obj;<br />  if (obj === null) return 'null';<br /><br />  for (var i in _object_types) {<br />    if (obj.constructor===_object_types[i]) return i;<br />  }<br />  return 'unknow';<br />}<br /><br />// 试数据和相关代?br />function MyObject() {<br />}<br />function MyObject2() {<br />}<br />MyObject2.prototype = new MyObject();<br /><br />window.execScript(''+<br />'Function CreateVBArray()' +<br />'  Dim a(2, 2)' +<br />'  CreateVBArray = a' +<br />'End Function', 'VBScript');<br /><br />document.writeln('<div id=dom style="display:none">dom<', '/div>');<br /><br />// 试代码<br />var ax = new ActiveXObject("Microsoft.XMLHTTP");<br />var dom = document.getElementById('dom');<br />var vba = new VBArray(CreateVBArray());<br />var obj = new MyObject();<br />var obj2 = new MyObject2();<br /><br />document.writeln(objectTypes(vba), '<br>');<br />document.writeln(objectTypes(ax), '<br>');<br />document.writeln(objectTypes(obj), '<br>');<br />document.writeln(objectTypes(obj2), '<br>');<br />document.writeln(objectTypes(dom), '<br>');<br /><br />在这个例子中Q我们发现constructor属性被实现得ƈ不完整。对于DOM对象、ActiveX对象<br />来说q个属性都没有正确的返回?br /><br />切的说QDOMQ包括Image)对象与ActiveX对象都不是标准JavaScript的对象体pM的,<br />因此它们也可能会h自己的constructor属性,q有着与JavaScript不同的解释。因此,<br />JavaScript中不l护它们的constructor属性,是具有一定的合理性的?br /><br />另外的一些单体对?而非构造器)Q也不具有constructor属性,例如“Math”和“Debug”?br />“Global”和“RegExp对象”。他们是JavaScript内部构造的Q不应该公开构造的l节?br /><br />我们也发现实例obj的constructor指向function MyObject()。这说明JavaScriptl护了对<br />象的constructor属性。——这与一些h惌的不一栗?br /><br />然而再接下来,我们发现MyObject2()的实例obj2的constructor仍然指向function MyObject()?br />管q很说不通,然而现实的如此。——这到底是ؓ什么呢Q?br /><br />事实上,仅下面的代码Q?br />--------<br />function MyObject2() {<br />}<br /><br />obj2 = new MyObject2();<br />document.writeln(MyObject2.prototype.constructor === MyObject2);<br />--------<br />构造的obj2.constructor正的指向function MyObject2()。事实上Q我们也会注意到q?br />U情况下QMyObject2的原型属性的constructor也正的指向该函数。然而,׃JavaScript<br />要求指定prototype对象来构造原型链Q?br />--------<br />function MyObject2() {<br />}<br />MyObject2.prototype = new MyObject();<br /><br />obj2 = new MyObject2();<br />--------<br />q时Q再讉Kobj2Q将会得到新的原?也就是MyObject2.prototype)的constructor属性?br />因此Q一切很明了Q原型的属性媄响到构造过E对对象的constructor的初始设定?br /><br />作ؓ一U补充的解决问题的手D,JavaScript开发规范中说“need to remember to reset<br />the constructor property'Q要求用戯行设定该属性?br /><br />所以你会看到更规范的JavaScript代码要求q样书写Q?br />//---------------------------------------------------------<br />// l护constructor属性的规范代码<br />//---------------------------------------------------------<br />function MyObject2() {<br />}<br />MyObject2.prototype = new MyObject();<br />MyObject2.prototype.constructor = MyObject2;<br /><br />obj2 = new MyObject2();<br /><br />更外一U解决问题的ҎQ是在function MyObject()中去重置该倹{当Ӟq样会<br />得执行效率稍低一点点Q?br />//---------------------------------------------------------<br />// l护constructor属性的W二U方?br />//---------------------------------------------------------<br />function MyObject2() {<br />  this.constructor = arguments.callee;<br />  // or, this.constructor = MyObject2;<br /><br />  // ...<br />}<br />MyObject2.prototype = new MyObject();<br /><br />obj2 = new MyObject2();<br /><br /> 5). 析构问题<br /> ------<br /> JavaScript中没有析构函敎ͼ但却有“对象析构”的问题。也是_管我们?br />知道一个对象什么时候会被析构,也不能截获它的析构过Eƈ处理一些事务。然而,<br />在一些不多见的时候,我们会遇到“要求一个对象立x构”的问题?br /><br />问题大多数的时候出现在对ActiveX Object的处理上。因为我们可能在JavaScript<br />里创Z一个ActiveX ObjectQ在做完一些处理之后,我们又需要再创徏一个。?br />如果原来的对象供应?Server)不允许创建多个实例,那么我们需要在JavaScript<br />中确保先前的实例是已l被释放q了。接下来Q即使Server允许创徏多个实例Q?br />在多个实例间允许׃n数据(例如OS的授权,或者资源、文件的?Q那么我们在?br />实例中的操作可能会出问题?br /><br />可能q是有h不明白我们在说什么,那么我就举一个例子:如果创徏一个Excel对象Q?br />打开文gQ,然后我们save它,然后关闭q个实例。然后我们再创徏Excel对象q打开<br />同一文g。——注意这时JavaScript可能q没有来得及析构前一个对象。——这时我?br />再想Saveq个文gQ就发现p|了。下面的代码CZq种情况Q?br />//---------------------------------------------------------<br />// JavaScript中的析构问题(ActiveX ObjectCZ)<br />//---------------------------------------------------------<br /><script><br />var strSaveLocation = 'file:///E:/1.xls'<br /><br />function createXLS() {<br />  var excel = new ActiveXObject("Excel.Application");<br />  var wk = excel.Workbooks.Add();<br />  wk.SaveAs(strSaveLocation);<br />  wk.Saved = true;<br /><br />  excel.Quit();<br />}<br /><br />function writeXLS() {<br />  var excel = new ActiveXObject("Excel.Application");<br />  var wk = excel.Workbooks.Open(strSaveLocation);<br />  var sheet = wk.Worksheets(1);<br />  sheet.Cells(1, 1).Value = '试字符?;<br />  wk.SaveAs(strSaveLocation);<br />  wk.Saved = true;<br /><br />  excel.Quit();<br />}<br /></script><br /><body><br />  <button onclick="createXLS()">创徏</button><br />  <button onclick="writeXLS()">重写</button><br /></body> <br /><br />在这个例子中Q在本地文g操作时ƈ不会出现异常。——最多只是有一些内存垃<br />圾而已。然而,如果strSaveLocation是一个远E的URLQ这时本地将会保存一?br />文g存取权限的凭证,而且同时只能一?q程?实例来开启该excel文q存<br />储。于是如果反复点?重写"按钮Q就会出现异常?br /><br />——注意,q是在SPS中操作共享文件时的一个实例的化代码。因此,它ƈ?br />“学术的”无聊讨论,而且工程中的实际问题?br /><br />解决q个问题的方法很复杂。它涉及C个问题:<br />  - 本地凭证的释?br />  - ActiveX Object实例的释?br /><br />下面我们先从JavaScript中对象的“失效”问题说赗简单的_<br />  - 一个对象在其生存的上下文环境之外,即会失效?br />  - 一个全局的对象在没有被执?引用)的情况下Q即会失效?br /><br />例如Q?br />//---------------------------------------------------------<br />// JavaScript对象何时失效<br />//---------------------------------------------------------<br />function testObject() {<br />  var _obj1 = new Object();<br />}<br /><br />function testObject2() {<br />  var _obj2 = new Object();<br />  return _obj2;<br />}<br /><br />// CZ1<br />testObject();<br /><br />// CZ2<br />testObject2()<br /><br />// CZ3<br />var obj3 = testObject2();<br />obj3 = null;<br /><br />// CZ4<br />var obj4 = testObject2();<br />var arr = [obj4];<br />obj3 = null;<br />arr = [];<br /><br />在这四个CZ中:<br />  - “示?”在函数testObject()中构造了_obj1Q但是在函数退出时Q?br />    它就已经d了函数的上下文环境,因此_obj1失效了;<br />  - “示?”中QtestObject2()中也构造了一个对象_obj2q传出,?br />    此对象有了“函数外”的上下文环?和生存周?Q然而由于函?br />    的返回值没有被其它变量“持有”,因此_obj2也立卛_效了Q?br />  - “示?”中QtestObject2()构造的_obj2被外部的变量obj3持用了,<br />    q时Q直到“obj3=null”这行代码生效时Q_obj2才会因ؓ引用关系<br />    消失而失效?br />  - 与示?相同的原因,“示?”中的_obj2会在“arr=[]”这行代?br />    之后才会失效?br /><br />但是Q对象的“失效”ƈ不等会“释䏀。在JavaScriptq行环境的内部,?br />有Q何方式来切地告诉用户“对象什么时候会释放”。这依赖于JavaScript<br />的内存回收机制。——这U策略与.NET中的回收机制是类同的?br /><br />在前面的Excel操作CZ代码中,对象的所有者,也就?EXCEL.EXE"q个q程<br />只能在“ActiveX Object实例的释䏀之后才会发生。而文件的锁,以及操作<br />pȝ的权限凭证是与进E相关的。因此如果对象仅是“失效”而不是“释䏀,<br />那么其它q程处理文g和引用操作系l的权限凭据时就会出问题?br /><br />——有些h说这是JavaScript或者COM机制的BUG。其实不是,q是QS、テQ?br />和JavaScript之间的一U复杂关pLD的,而非独立的问题?br /><br />Microsoft公开了解册U问题的{略Q主动调用内存回收过E?br /><br />?微Y?JScript中提供了一个CollectGarbage()q程(通常UGCq程)Q?br />GCq程用于清理当前IE中的“失效的对象׃”,也就是调用对象的析构q程?br /><br />在上例中调用GCq程的代码是Q?br />//---------------------------------------------------------<br />// 处理ActiveX ObjectӞGCq程的标准调用方?br />//---------------------------------------------------------<br />function writeXLS() {<br />  //(?..)<br /><br />  excel.Quit();<br />  excel = null;<br />  setTimeout(CollectGarbage, 1);<br />}<br /><br />W一行代码调用excel.Quit()Ҏ来得excelq程中止q出,q时׃JavaScript<br />环境执有excel对象实例Q因此excelq程q不实际中止?br /><br />W二行代码excel为nullQ以清除对象引用Q从而对象“失效”。然而由?br />对象仍旧在函C下文环境中,因此如果直接调用GCq程Q对象仍然不会被清理?br /><br />W三行代码用setTimeout()来调用CollectGarbage函数Q时间间隔设?1'Q只<br />是得GCq程发生在writeXLS()函数执行完之后。这样excel对象满了“能?br />GC清理”的两个条gQ没有引用和d上下文环境?br /><br />GCq程的用,在用了ActiveX Object的JS环境中很有效。一些潜在的ActiveX<br />Object包括XML、VML、OWC(Office Web Componet)、flashQ甚臛_括在JS中的VBArray?br />从这一Ҏ看,ajax架构׃采用了XMLHTTPQƈ且同时要满“不切换面”的<br />Ҏ,因此在适当的时候主动调用GCq程Q会得到更好的效率用UI体验?br /><br />事实上,即使用GCq程Q前面提到的excel问题仍然不会被完全解冟뀂因为IEq?br />~存了权限凭据。ə늚权限凭据被更新的唯一ҎQ只能是“切换到新的面”,<br />因此事实上在前面提到的那个SPS目中,我采用的Ҏq不是GCQ而是下面q一<br />D代码:<br />//---------------------------------------------------------<br />// 处理ActiveX Object旉用的面切换代码<br />//---------------------------------------------------------<br />function writeXLS() {<br />  //(?..)<br /><br />  excel.Quit();<br />  excel = null;<br /> <br />  // 下面代码用于解决IE call Excel的一个BUG, MSDN中提供的Ҏ:<br />  //   setTimeout(CollectGarbage, 1);<br />  // ׃不能清除(或同?|页的受信Q状? 所以将DSaveAs(){方法在<br />  // 下次调用时无?<br />  location.reload();<br />}<br /><br />最后之最后,关于GC的一个补充说明:在IEH体被最化ӞIE会d调用一?br />CollectGarbage()函数。这使得IEH口在最化之后Q内存占用会有明显改善?br /><br />八、JavaScript面向对象的支?br />~~~~~~~~~~~~~~~~~~<br />(l?<br /><br />4. 实例和实例引?br />--------<br />?NET Framework对CTS(Common Type System)U定“一切都是对象”,q分为“值类型”和“引用类型”两U。其中“值类型”的对象在{换成“引用类型”数据的q程中,需要进行一个“装”和“拆”的q程?br /><br />在JavaScript也有同样的问题。我们看到的typeof关键字,q回以下六种数据cdQ?br />"number"?string"?boolean"?object"?function" 和?undefined"?br /><br />我们也发现JavaScript的对象系l中Q有String、Number、Function、Booleanq四U对象构造器。那么,我们的问题是Q如果有一个数字AQtypeof(A)的结果,到底会是'number'呢,q是一个构造器指向function Number()的对象呢Q?br /><br />//---------------------------------------------------------<br />// 关于JavaScript的类型的试代码<br />//---------------------------------------------------------<br />function getTypeInfo(V) {<br />  return (typeof V == 'object' ?  'Object, construct by '+V.constructor<br />   : 'Value, type of '+typeof V);<br />}<br /><br />var A1 = 100;<br />var A2 = new Number(100);<br /><br />document.writeln('A1 is ', getTypeInfo(A1), '<BR>');<br />document.writeln('A2 is ', getTypeInfo(A2), '<BR>');<br />document.writeln([A1.constructor === A2.constructor, A2.constructor === Number]);<br /><br />试代码的执行结果如下:<br />-----------<br /> A1 is Value, type of number<br /> A2 is Object, construct by function Number() { [native code] } <br /> true,true<br />-----------<br /><br />我们注意刎ͼA1和A2的构造器都指向Number。这意味着通过constructor属性来识别对象Q?有时)比typeof更加有效。因为“值类型数据”A1作ؓ一个对象来看待Ӟ与A2有完全相同的Ҏ?br /><br />——除了与实例引用有关的问题?br /><br />参考JScript手册Q我们对其它基础cd和构造器做相同考察Q可以发玎ͼ<br />  - 基础cd中的undefined、number、boolean和stringQ是“值类型”变?br />  - 基础cd中的array、function和objectQ是“引用类型”变?br />  - 使用new()Ҏ构造出对象Q是“引用类型”变?br /><br />下面的代码说明“值类型”与“引用类型”之间的区别Q?br />//---------------------------------------------------------<br />// 关于JavaScriptcdpȝ中的?引用问题<br />//---------------------------------------------------------<br />var str1 = 'abcdefgh', str2 = 'abcdefgh';<br />var obj1 = new String('abcdefgh'), obj2 = new String('abcdefgh');<br /><br />document.writeln([str1==str2, str1===str2], '<br>');<br />document.writeln([obj1==obj2, obj1===obj2]);<br /><br />试代码的执行结果如下:<br />-----------<br /> true, true<br /> false, false<br />-----------<br /><br />我们看到Q无论是{D?==)Q还是全{运?===)Q对“对象”和“值”的理解都是不一L?br /><br />更进一步的理解q种现象Q我们知道:<br />  - q算l果为值类型,或变量ؓ值类型时Q等?或全{?比较可以得到预想l果<br />  - (即包含相同的数据,)不同的对象实例之间是不等?或全{??br />  - 同一个对象的不同引用之间Q是{?==)且全{?===)?br /><br />但对于StringcdQ有一点补充:ҎJScript的描qͼ两个字符串比较时Q只要有一个是值类型,则按值比较。这意味着在上面的例子中,代码“str1==obj1”会得到l果true。而全{?===)q算需要检变量类型的一致性,因此“str1===obj1”的l果q回false?br /><br />JavaScript中的函数参数L传入值参Q引用类?的实?是作为指针g入的。因此函数可以随意重写入口变量,而不用担心外部变量被修改。但是,需要留意传入的引用cd的变量,因ؓ对它Ҏ调用和属性读写可能会影响到实例本w。——但Q也可以通过引用cd的参数来传出数据?br /><br />最后补充说明一下,值类型比较会逐字节检对象实例中的数据,效率低但准确性高Q而引用类型只实例指针和数据cdQ因此效率高而准性低。如果你需要检两个引用类型是否真的包含相同的数据Q可能你需要尝试把它{换成“字W串值”再来比较?br /><br />6. 函数的上下文环境<br />--------<br />只要写过代码Q你应该知道变量是有“全局变量”和“局部变量”之分的。绝大多数的<br />JavaScriptE序员也知道下面q些概念Q?br />//---------------------------------------------------------<br />// JavaScript中的全局变量与局部变?br />//---------------------------------------------------------<br />var v1 = '全局变量-1';<br />v2 = '全局变量-2';<br /><br />function foo() {<br />  v3 = '全局变量-3';<br /><br />  var v4 = '只有在函数内部ƈ使用var定义的,才是局部变?;<br />}<br /><br />按照通常对语a的理解来_不同的代码调用函敎ͼ都会拥有一套独立的局部变量?br />因此下面q段代码很容易理解:<br />//---------------------------------------------------------<br />// JavaScript的局部变?br />//---------------------------------------------------------<br />function MyObject() {<br />  var o = new Object;<br /><br />  this.getValue = function() {<br />    return o;<br />  }<br />}<br /><br />var obj1 = new MyObject();<br />var obj2 = new MyObject();<br />document.writeln(obj1.getValue() == obj2.getValue());<br /><br />l果昄falseQ表明不?实例的方?调用q回的局部变量“obj1/obj2”是不相同?br /><br />变量的局部、全局Ҏ与OOP的封装性中的“私?private)”、“公开(public)”具有类同性。因此绝大多数资料L以下面的方式来说明JavaScript的面向对象系l中的“封装权限别”问题:<br />//---------------------------------------------------------<br />// JavaScript中OOP装?br />//---------------------------------------------------------<br />function MyObject() {<br />  // 1. U有成员和方?br />  var private_prop = 0;<br />  var private_method_1 = function() {<br />    // ...<br />    return 1<br />  }<br />  function private_method_2() {<br />    // ...<br />    return 1<br />  }<br /><br />  // 2. ҎҎ<br />  this.privileged_method = function () {<br />    private_prop++;<br />    return private_prop + private_method_1() + private_method_2();<br />  }<br /><br />  // 3. 公开成员和方?br />  this.public_prop_1 = '';<br />  this.public_method_1 = function () {<br />    // ...<br />  }<br />}<br /><br />// 4. 公开成员和方?2)<br />MyObject.prototype.public_prop_1 = '';<br />MyObject.prototype.public_method_1 = function () {<br />  // ...<br />}<br /><br />var obj1 = new MyObject();<br />var obj2 = new MyObject();<br /><br />document.writeln(obj1.privileged_method(), '<br>');<br />document.writeln(obj2.privileged_method());<br /><br />在这里,“私?private)”表明只有在(构?函数内部可访问,而“特?privileged)”是Ҏ一U存取“私有域”的“公开(public)”方法。“公开(public)”表明在(构?函数外可以调用和存取?br /><br />除了上述的封装权限之外,一些文还介绍了其它两U相关的概念Q?br />  - 原型属性:Classname.prototype.propertyName = someValue<br />  - (c?静态属性:Classname.propertyName = someValue <br /><br />然而,从面向对象的角度上来Ԍ上面q些概念都很难自圆其_JavaScriptI竟是ؓ何、以及如何划分出q些装权限和概忉|的呢Q?br /><br />——因为我们必L意到下面q个例子所带来的问题:<br />//---------------------------------------------------------<br />// JavaScript中的局部变?br />//---------------------------------------------------------<br />function MyFoo() {<br />  var i;<br /><br />  MyFoo.setValue = function (v) {<br />     i = v;<br />  }<br />  MyFoo.getValue = function () {<br />     return i;<br />  }<br />}<br />MyFoo();<br /><br />var obj1 = new Object();<br />var obj2 = new Object();<br /><br />// 试一<br />MyFoo.setValue.call(obj1, 'obj1');<br />document.writeln(MyFoo.getValue.call(obj1), '<BR>');<br /><br />// 试?br />MyFoo.setValue.call(obj2, 'obj2');<br />document.writeln(MyFoo.getValue.call(obj2));<br />document.writeln(MyFoo.getValue.call(obj1));<br />document.writeln(MyFoo.getValue());<br /><br />在这个测试代码中Qobj1/obj2都是Object()实例。我们用function.call()的方式来调用setValue/getValueQ得在MyFoo()调用的过E中替换this为obj1/obj2实例?br /><br />然而我们发现“测试二”完成之后,obj2、obj1以及function MyFoo()所持有的局部变量都q回了“obj2”。——这表明三个函数使用了同一个局部变量?br /><br />由此可见QJavaScript在处理局部变量时Q对“普通函数”与“构造器”是分别对待的。这U处理策略在一些JavaScript相关的资料中被解释作“面向对象中的私有域”问题。而事实上Q我更愿意从源代码一U来告诉你真相:q是对象的上下文环境的问题。——只不过从表面看去,“上下文环境”的问题被{嫁到对象的封装性问题上了?br /><br />(在阅M面的文字之前Q?先做一个概忉|的说明Q?br />  - 在普通函CQ上下文环境被window对象所持有<br /> - 在“构造器和对象方法”中Q上下文环境被对象实例所持有<br /><br />在JavaScript的实C码中Q每ơ创Z个对象,解释器将为对象创Z个上下文环境链,用于存放对象在进入“构造器和对象方法”时对function()内部数据的一个备份。JavaScript保证q个对象在以后再q入“构造器和对象方法”内部时QL持有该上下文环境Q和一个与之相关的this对象。由于对象可能有多个ҎQ且每个Ҏ可能又存在多层嵌套函敎ͼ因此q事实上构成了一个上下文环境的树型链表结构。而在构造器和对象方法之外,JavaScript不提供Q何访?该构造器和对象方法的)上下文环境的Ҏ?br /><br />而言之:<br />  - 上下文环境与对象实例调用“构造器和对象方法”时相关Q而与(普?函数无关<br />  - 上下文环境记录一个对象在“构造函数和对象Ҏ”内部的U有数据<br />  - 上下文环境采用链式结构,以记录多层的嵌套函数中的上下?br /><br />׃上下文环境只与构造函数及其内部的嵌套函数有关Q重新阅d面的代码Q?br />//---------------------------------------------------------<br />// JavaScript中的局部变?br />//---------------------------------------------------------<br />function MyFoo() {<br />  var i;<br /><br />  MyFoo.setValue = function (v) {<br />     i = v;<br />  }<br />  MyFoo.getValue = function () {<br />     return i;<br />  }<br />}<br />MyFoo();<br /><br />var obj1 = new Object();<br />MyFoo.setValue.call(obj1, 'obj1');<br /><br />我们发现setValue()的确可以讉KC于MyFoo()函数内部的“局部变量i”,但是׃setValue()Ҏ的执有者是MyFoo对象(C函数也是对象)Q因此MyFoo对象拥有MyFoo()函数的唯一一份“上下文环境”?br /><br />接下来MyFoo.setValue.call()调用虽然为setValue()传入了新的this对象Q但实际上拥有“上下文环境”的仍旧是MyFoo对象。因此我们看到无论创建多个obj1/obj2Q最l操作的都是同一个私有变量i?br /><br />全局函数/变量的“上下文环境”持有者ؓwindowQ因此下面的代码说明了“ؓ什么全局变量能被L的对象和函数讉K”:<br />//---------------------------------------------------------<br />// 全局函数的上下文<br />//---------------------------------------------------------<br />/*<br />function Window() {<br />*/<br />  var global_i = 0;<br />  var global_j = 1;<br /><br />  function foo_0() {<br />  }<br /><br />  function foo_1() {<br />  }<br />/*<br />}<br /><br />window = new Window();<br />*/<br /><br />因此我们可以看到foo_0()与foo_1()能同时访问global_i和global_j。接下来的推论是Q上下文环境军_了变量的“全局”与“私有”。而不是反q来通过变量的私有与全局来讨Z下文环境问题?br /><br />更进一步的推论是:JavaScript中的全局变量与函敎ͼ本质上是window对象的私有变量与Ҏ。而这个上下文环境块,位于所?window对象内部?对象实例的上下文环境链表的顶端,因此都可能访问到?br /><br />用“上下文环境”的理论Q你可以利地解释在本小节中Q有兛_量的“全局Q局部”作用域的问题,以及有关对象Ҏ的封装权限问题。事实上Q在实现JavaScript的C源代码中Q这个“上下文环境”被叫做“JSContext”,q作为函敎ͼҎ的第一个参C入。——如果你有兴,你可以从源代码中证实本小节所q的理论?br /><br />另外Q《JavaScript权威指南》这本书中第4.7节也讲述了这个问题,但被叫做“变量的作用域”。然而重要的是,q本书把问题讲反了。——作者试囄“全局、局部的作用域”,来解释生这U现象的“上下文环境”的问题。因此这个小节显得凌p且难以自圆其说?br /><br />不过?.6.3节Q作者也提到了执行环?execution context)的问题,q就与我们这里说的“上下文环境”是一致的了。然而更ȝ的是Q作者又读者引错了ҎQ试囄函数的上下文环境去解释DOM和ScriptEngine中的问题?br /><br />但这本书在“上下文环境链表”的查询方式上的讲述Q是正确的而合理的。只是把q个叫成“作用域”有点不对,或者不妥。?br /></font> <img src ="http://www.aygfsteel.com/zengke/aggbug/79906.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/zengke/" target="_blank">曄</a> 2006-11-08 17:07 <a href="http://www.aygfsteel.com/zengke/articles/79906.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <a href="http://www.aygfsteel.com/" title="狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频">狠狠久久亚洲欧美专区_中文字幕亚洲综合久久202_国产精品亚洲第五区在线_日本免费网站视频</a> </div> </footer> վ֩ģ壺 <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ĵ</a>| <a href="http://" target="_blank">ƽ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">³ľ</a>| <a href="http://" target="_blank">¡</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ĭ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">߮</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Դ</a>| <a href="http://" target="_blank">ݳ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">մ</a>| <a href="http://" target="_blank">ӽ</a>| <a href="http://" target="_blank">Ƕ</a>| <a href="http://" target="_blank">ƽ̶</a>| <a href="http://" target="_blank">Ϫ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">ͩ</a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank"></a>| <a href="http://" target="_blank">Ԫ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>