PHP中的mysql_pconnect一直是大家所拿过来做比较的,但对于很多开发者来说,只知道一件事情,那就是mysql_pconnect是长连接,而mysql_connect是普通的连接。既然PHP没有所谓的连接池,那为什么又会有mysql_pconnect的功能呢?
本文是网上而来的,也是我难得看到一篇关于mysql_pconnect的文章。所以摘抄下来
原文来自:mysql_pconnect的水挺深,apache下的数据库长连接
php的mysql持久化连接,美好的目标,却拥有糟糕的口碑,往往令人敬而远之。这到底是为啥么。近距离观察后发现,这家伙也不容易啊,要看apache的脸色,还得听mysql指挥。
对于做为apache模块运行的php来说,要实现mysql持久化连接,首先得取决于apache这个web服务器是否支持Keep-Alive。
Keep-Alive是什么东西?它是http协议的一部分,让我们复习一下没有Keep-Alive的http请求,从客户在浏览器输入一个 有效url地址开始,浏览器就会利用socket向url对应的web服务器发送一条tcp请求,这个请求成功一次就得需要来回握三次手才能确定,成功以 后,浏览器利用socket tcp连接资源向web服务器请求http协议,发送以后就等着web服务器把http返回头和body发送回来,发回来后浏览器关闭socket连接, 然后做http返回头和body的解析工作,最后呈现在浏览器上的就是漂亮的页面了。这里面有什么问题呢?tcp连接需要三次握手,也就是来回请求三次方 能确定一个tcp请求是否成功,然后tcp关闭呢?来回需要4次请求才能完成!每次http请求就3次握手,4次拜拜,这来来回回的不嫌累啊,多少时间和 资源都被浪费在socket连接关闭上了,能不能一次socket tcp连接发送多次http请求呢?于是Keep-Alive就应运而生,http/1.0里需要客户端自己在请求头加入 Connection:Keep-alive方能实现,在这里我们只考虑http1.1了,只需要设置一下apache,让它默认就是Keep- Alive持久连接模式(apache必须1.2+才能支持Keep-Alive).在httpd.conf里找到KeepAive配置项,果断设置为 On,MaxKeepAliveRequests果断为0(一个持久tcp最多允许的请求数,如果过小,很容易在tcp未过期的情况下,达到最大连接,那 下次连接就又是新的tcp连接了,这里设置0表示不限制),然后对于mysql_pconnect最重要的选项KeepAliveTimeout设置为 15(表示15秒).
好了,重启apache,测试一下,赶紧写行东西
PHP代码
- <?php
- echo "Apache进程号:".getmypid();
- ?>
很简单,获取当前php执行者(apache)的进程号,用浏览器浏览这个页面,看到什么?对,有看到一串进程号数字,15秒内,连续刷新页面,看 看进程号有无变化?木有吧?现在把手拿开,交叉在胸前,度好时间,1秒,2秒,3,...15,16。好,过了15秒了,再去刷新页面,进程号有没有变 化?变了!又是一个新的apache进程了,为什么15秒后就变成新的进程了?记得我们在apache里设置的KeepAliveTimeout吗?它的 值就是15秒.现在我们应该大致清楚了,在web服务器默认打开KeepAlive的情况下,客户端第一次http成功请求后,apache不会立刻断开 socket,而是一直监听来自这一客户端的请求,监听多久?根据KeepAliveTimeout选项配置的时间决定,一旦超过这一时间,apache 就会断开socket了,那么下次同一客户端再次请求,apache就会新开一个进程来相应。所以我们之前15内不停的刷新页面,看到的进程号都是一致 的,表明是浏览器请求给了同一个apache进程。
浏览器是怎么知道不需要tcp连接就可以直接发送http请求呢?因为http返回头里就会带上Connection:keep- alive,Keep-alive:15两行,意思就是让客户端浏览器明白,这次socket连接我这边还没关闭呢,你可以在15内继续使用这个连接,并 发送http请求,于是乎浏览器就知道应该怎么做了.
那么,php的mysql连接资源是怎么被hold住的呢,这需要查看php的mysql_pconnect的函数代码,我看了下,大概的做法 就是mysql_pconnect根据当前apache进程号,生成hash key,找hash表内有无对应的连接资源,没有则推入hash表,有则直接使用。有些代码片段可以说明(具体可查看php5.3.8源码 ext/mysql/php_mysql.c文件690行php_mysql_do_connect函数)
C++代码
- #1.生成hash key
- user=php_get_current_user();
- hashed_details_length = spprintf(&hashed_details, 0, "mysql__%s_", user);
- #2.如果未找到已有资源,就推入hash表,名字叫persistent_list,如果找到就直接使用
-
- if (zend_hash_find(&EG(persistent_list), hashed_details, hashed_details_length+1, (void **) &le)==FAILURE) {
- ...
- ...
-
- Z_TYPE(new_le) = le_plink;
- new_le.ptr = mysql;
- if (zend_hash_update(&EG(persistent_list), hashed_details, hashed_details_length+1, (void *) &new_le, sizeof(zend_rsrc_list_entry), NULL)==FAILURE) {
- ...
- ...
- }
-
- }else{
- ...
- ...
- mysql = (php_mysql_conn *) le->ptr;
- ...
- ...
-
- }
zend_hash_find比较容易看明白,原型是zend_hash_find(hash表,key名,key长,value);如果找到,value就有值了。
说完Keep-Alive,该到mysql家串串门了,说的是mysql_pconnect,怎么能绕开mysql的设置。
影响mysql_pconnect最重要的两个参数就是wait_timeout和interactive_timeout,它们是什么东西?先撇一边,首先让我们把上面的代码改动一下php代码
PHP代码
- <?php
- $conn = mysql_pconnect("localhost","root","123456") or die("Can not connect to mysql");
- echo "Mysql线程号:".mysql_thread_id($conn)."<br/>";
- echo "Apache进程号".getmypid();
- ?>
以上的代码没啥好解释的,让我们用浏览器浏览这个页面,看到什么?看到两个显眼的数字。一个是mysql线程号,一个是apache进程号,好 了,15秒后再刷新这个页面,发现这两个id都变了,因为已经是新的apache进程了,进程id是新的,hash key就变了,php只好重新连接mysql,连接资源推入persistent list。如果15内刷新呢?apache进程肯定不变,mysql线程号会变吗?答案得问mysql了。首先这个mysql_thread_id是什么 东西?shell方式登录mysql后执行命令'show processlist;',看到了什么?
mysql> show processlist;XML/HTML代码
- +-----+------+-----------+------+---------+------+-------+------------------+
- | Id | User | Host | db | Command | Time | State | Info |
- +-----+------+-----------+------+---------+------+-------+------------------+
- | 348 | root | localhost | NULL | Query | 0 | NULL | show processlist |
- | 349 | root | localhost | NULL | Sleep | 2 | | NULL |
- +-----+------+-----------+------+---------+------+-------+------------------+
,发现了很重要的信息,这个processlist列表就是记录了正在跑的线程,忽略Info列为show processlist那行,那行是你当前shell登录mysql的线程。php连接mysql的线程就是Id为349那行,如果读者自己做测试,应该 知道这个Id=349在你的测试环境里是另外一个值,我们把这个值和网页里输出的mysql_thread_id($conn)做做比较,对!他们是一样 的。接下来最重要的是观察Command列和Time列,Command = Sleep,表明什么?表明我们mysql_pconnect连接后就一直在sleep,Time字段就告诉我们,这个线程Sleep了多久,那么 Sleep了多久这个线程才能作废呢?那就是wait_timeout或者interactive_timeout要做的工作了,他们默认的值都是8小 时,天啊,太久了,所以如果说web服务器关掉KeepAlive支持,那个这个processlist很容易就被撑爆,就爆出那个Too many connections的错误了,max_connectiosns配置得再多也没用。为了观察这两个参数,我们可以在mysql配置文件my.cnf里 设置这两个值,找到[mysqld]节点,在里面设置多两行
配置代码
- interactive_timeout = 60
- wait_timeout = 30
配置完后,重启mysql,shell登录mysql,这时候show processlist可以发现只有当前线程。然后运行那个带有mysql_pconnect的php页面,再回来mysql端show processlist可发现,多了一个Commond为Sleep的线程,不停的show processlist(方向键上+enter键)观察Time列的变化2,5,10..14!,突然那个Sleep线程程被kill掉了,咋回事,还没 到30秒呢,噢!忘了修改一下apache keepalive的参数了,把KeepAliveTimeOut从15改成120(只为观察,才这么改),重启apache.刷新那个页面,好,开始不 停的show processlist,2..5..10..14,15,..20...26....28,29!线程被kill,这次是因为wait_timeout 起了作用,浏览器那边停了30秒,30内如果浏览器刷新,那这个Time又会从0开始计时。这种连接不属于interactive connection(mysql shell登录那种连接就属于interactive connection),所以采用了wait_timeout的值。如果mysql_pconnect的第4个参数改改呢
PHP代码
- <?php
- $conn = mysql_pconnect('localhost','root','123456',MYSQL_CLIENT_INTERACTIVE);
- echo "Mysql线程号:".mysql_thread_id($conn)."<br/>";
- echo "Apache进程号:".getmypid();
- ?>
刷新下页面,mysql那边开始刷show processlist,这回Time > 30也不会被kill,>60才被kill了,说明设置了MYSQL_CLIENT_INTERACTIVE,就会被mysql视为 interactive connection,那么这次php的mysql连接在60秒内未刷新的情况下,何时作废将取决于mysql的interactive_timeout 的配置值。
总结:php的mysql_pconnect要达到功效,首先必须保证apache是支持keep alive的,其次KeepAliveTimeOut应该设置多久呢,要根据自身站点的访问情况做调整,时间太短,keep alive没啥意义,时间太长,就很可能为一个闲客户端连接牺牲很多服务器资源,毕竟hold住socket监听进程是要消耗cpu内存的.最后 apache的KeepAliveTimeOut配置得和mysql的time out配置要有个平衡点,联系以上的观察,假设mysql_pconnect未带上第4个参数,如果apache的KeepAliveTimeOut设置 的秒数比wait_timeout小,那真正对mysql_pconnect起作用的是apache而不是mysql的配置.这时如果mysql的 wait_timeout偏大,并发量大的情况下,很可能就一堆废弃的connection了,mysql这边如果不及时回收,那就很可能Too many connections了.可以如果KeepAliveTimeOut太大呢,又回到之前的问题,所以貌似Apache.KeepAliveTimeOu 比Mysql.wait_timeout 稍大,或者相等是比较好的方案,这样可以保证keep alive过期后,废弃的mysql连接可以及时被回收.
--------------
文章不算太长,看看即可,毕竟现在大多数项目 都开始用PDO了,但这样深究的文章还是有值得学习的地方的
尝试用mac的时候,有些都不太习惯。比如切换输入法,是command+space,而在windows下,是ctrl+space。
比如关闭窗口,是ctrl+w,而mac是command+w,退出程序还好。几乎都是command+q。这个倒习惯了
最大的不习惯是在写代码的时候,突然发现。。。没有home键和end键了。以前靠这个来快速定位到首部和尾部的。。。一下子纠结了。找了点资料才发现,原来是fn+left和fn+right可以当成home和end用。所以。。。猜测了一下delete的功能是通过fn+delete实现,结果,果然如此。。。默认的delete其实就是win键盘上的Backspace。。。慢慢慢慢就习惯了很多
找到一篇文章介绍快捷键的,备份一下:http://www.diybl.com/course/6_system/apple/200861/119083.html
在以下的列表中,「opt」为键盘上「Option键」的简称、「cmd」是「Command键」、 「ctrl」则是「Control键」的简称。作者表示所有按键都经过实验,但译者并没有亲自使用过所有的按键组合,所以本文内容仅供参考;如果您要尝试 没有使用过的按键组合,请自己小心。
一、开机时按下……
滑鼠按键 弹出抽取式媒介(2.4f1版以前的Boot ROM可能不包括退出CD片)
opt键 在配备「New World」韧体系统的机种上叫出「Open Firmware」开机系统选择功能。
cmd-opt键 按住这两个键,直到电脑发出二次声响,就会改以Mac OS 9开机。
cmd-x(有时只按住x键) 如果Mac OS 9和Mac OS X在同一个开机用的硬碟区段(partition)上,按这个键会强迫以OS X开机。
cmd-opt-shift-delete 跳过原定的启动磁碟,改以外接磁碟(或光碟机)开机。这个按键的主要作用,其实是强迫电脑不要从预设的启动磁碟读入系统档案,所以会产生从其他磁碟开机的 「副作用」。如果您的Mac是配备SCSI介面的机种,它会从编号(ID)最高的磁碟机往下搜寻,直到找出可以开机的磁碟区段为止。至於在配备IDE介面 的机种上则不确定它的搜寻顺序。
cmd-opt-shift-delete-# 从指定ID的SCSI磁碟开?#代表SCSI编号)。
cmd-opt-p-r 清除系统参数记忆体(PRAM),必须按住不放,等发出两次响声之后再放开。
cmd-opt-n-v 清除NV RAM,类似在Open Firmware中做「重置全部」(reset-all)的动作。
cmd-opt-o-f 开机时进入open firmware。
cmd-opt-t-v 强制Quadra AV机种使用外接电视机当作显示器。
cmd-opt-x-o 以唯读记忆体中所烧录的系统软体开机(仅适用於Mac Classic机种)。
cmd-opt-a-v 强制电脑辨识苹果AV显示器。
c 使用光碟开机。如果原先设定由OS X开机,但光碟机里没有放置开机光碟,则可能会改由OS 9开机。
d 强制以内建磁碟机开机。
n 按住n键直到萤幕上出现Mac标志,电脑会尝试透过BOOTP或TFTP以网路伺服器开机。
r 强制PowerBook重置萤幕设定。
t 强制配备FireWire介面的机种进入外接磁碟模式(FireWire Target Disk mode)。
shift 关闭所有延伸功能(OS 9或OS X之下的Classic环境)。
shift 关闭登入项目,同时也会关闭所有不必要的程式核心(kernel)延伸功能(也就是所谓安全开机模式,仅适用OS X 10.1.3或更新的系统版本)。
cmd 开机时关闭虚拟记忆体(Virtual Memory,仅适用OS 9或OS X之下的Classic环境)。
空白键 开机时启动延伸功能管理程式(OS 9或OS X之下的Classic环境)。
cmd-v 开机过程中显示控制台讯息(仅适用OS X)。
cmd-s 开机后进入单一使用者模式(仅适用OS X)。
cmd-opt-c-i 先将系统时钟设定为日期1989年9月20日,然后以这个按键组合开机,就可以看到萤幕上显示特殊的系统小秘密(仅适用於Mac IIci机种)。
cmd-opt-f-x 先将系统时钟设定为日期1990年3月19日,然后以这个按键组合开机,就可以看到萤幕上显示特殊的系统小秘密(仅适用於Mac IIfx机种)。
二、萤幕上出现小Mac笑脸时按下……
空白键 开机时启动延伸功能管理程式(OS 9或OS X之下的Classic环境)。
shift 关闭包括MacsBug(一种程式设计师工具程式)在内的所有延伸功能(OS 9或OS X之下的Classic环境)。
shift-opt 关闭除了MacsBug之外的所有延伸功能(OS 9或OS X之下的Classic环境)。
ctrl 中断开机过程,进入MacsBug除错模式。
三、系统画面出现后按下……
cmd-opt 当OS 9或OS X中的Classic环境连接磁碟机时,可以重建磁碟机的桌面档案。
opt 不要开启任何系统视窗(Mac OS 9)。
shift 在系统档案(Finder)启动时暂时不要开启系统视窗。这些视窗并没有被真的关闭,只要您重新开机,这些视窗都就会照常出现(Mac OS X)。
shift 不要执行任何「启动项目」软体(Mac OS 9)。
四、在系统画面中按下……
按住opt键,再以滑鼠游标
按视窗上的关闭方块 关闭所有的系统视窗(除了弹出式视窗之外);按cmd-opt-w键也可以获得一样的效果。
cmd-shift-opt-w 关闭所有的系统视窗(包括弹出式视窗)。
cmd-右箭头键 在档案视窗以列表模式显示时,开启一个档案夹。
cmd-opt-右箭头键 在档案视窗以列表模式显示时,重复开启档案夹、以及其下所包含的多层档案夹。
cmd-左箭头键 在档案视窗以列表模式显示时,关闭一个档案夹。
cmd-opt-左箭头键 在档案视窗以列表模式显示时,重复关闭档案夹、以及其下所包含的多层档案夹。
cmd-上箭头键 开启上一层档案夹。在Mac OS X中,如果事先并未选定档案夹、而且没有开启任何视窗,这个按键会开启现在使用者的专属目录。
cmd-opt-上箭头键 开启上一层档案夹,并关闭现用档案夹。
cmd-opt-shift-上箭头键 将桌面变成现用视窗,并且选择最上层磁碟机。
cmd-下箭头键 开启选取的项目。在Mac OS X中,如果事先并未选定档案夹、而且没有开启任何视窗,这个按键会开启桌面档案夹。
cmd-opt-下箭头键 开启选取的项目,并关闭现用的档案夹。
opt-滑鼠按键 按条列档案视窗中的小三角形图像时,可以显示或隐藏下层档案夹中的内容。
tab键 选择名称以下一个英文字母开头的档案夹。
shift-tab键 选择名称以上一个英文字母开头的档案夹。
cmd-delete 把选取的项目搬进垃圾桶
五、在系统画面中的「视窗」选单中……
cmd-选取项目 关闭视窗。
cmd-shift-选取项目 将弹出式视窗归位。
cmd-opt-选取项目 展开选取的视窗,并关闭其他所有视窗。
ctrl-选取项目 展开选取的视窗,并隐藏其他视窗的内容。
·ctrl-opt-选取项目 启动选取视窗,并展开所有的其他视窗。
六、系统启动完毕之后……
在有电源按钮的机种上
电源按钮 在萤幕上显示包括「关机」、「睡眠」、以及「重新开机」按钮的对话框(请参阅下一节)。
cmd-ctrl-电源按钮 强制重新开机。这种方式非必要不建议使用,因为有可能损坏磁碟上的资料内容。
ctrl-cmd-opt-电源按钮 快速关机。
cmd- 电源按钮 启动程式除错软体(如果已事先安装的话)。较早期的Mac(例如Mac II时代的机器)需要先安装由Paul Mercer所写的除错延伸功能(debugger init)来使用这个功能;不过这个功能在配备68040处理器的Mac机种上,已经成为系统韧体内容的一部份。
cmd-opt-电源按钮 让后期型式的PowerBook和桌上型Mac进入睡眠状态。
cmd-opt-ctrl-电源按钮 重新设定电源管理程式(Power Manager;仅适用PowerBook 500系列)。
shift-fn-ctrl-电源按钮 重新设定电源管理程式(Power Manager;仅适用PowerBook G3与G4系列)。
-------------
以上内容不可全信,因为到lion的时候,很多快捷键都换掉了。一些界面、常见操作都和雪豹不太一样了啦
最后再附上一年所谓的隐藏快捷键:http://jaylan.anyday.com.tw/?p=212
以下是For Mac OSX用的快速鍵
1. Apple Logo
快速鍵 : Option-Shift-K
2. Zero Brightness~馬上把螢幕亮度切至無亮度
快速鍵 : Control-Shift-Eject
Note. Instantly turn your display off without logging out from the system.
3. Adjust Volume Bar~微調音量,可將原本一格的音量調整再細分為四等份,作四分之一的微調
快速鍵 : Option-Shift-F4 / Option-Shift-F5
Note. Increase/decrease your volume bar by a quarter each time it’s invoked. This is particularly useful for fine tuning Mac with bombastic sound system.
4. Double Buffer~Control-K可剪下游標後方的整段文字(不需反白),Control-Y可將用Control-K剪下的文字貼上,類似Copy & Paste的功能
快速鍵 : Control-K (Kill) and Control-Y (Yank)
Note. Like, Cut and Paste, combination of Kill and Yank can help you organize your text easily. Cut followed by Kill grants you double text buffer.
5. Home and End~將游標移至文章的首字及尾字
快速鍵 : Control-A (Home) and Control-E (End)
Note. This is pretty much the substitution for Windows button HOME and END. Pressing Command-← or Command-→ performs the same action.
6. Delete and Backspace~就是Delete 跟 Backspace的快速鍵,這個Delete(Control-D)的快速鍵筆使用筆電時可按的fn+delete好按得多
快速鍵 : Control-D (Delete) and Control-H (Backspace)
Note. In Windows, we’ve got two buttons for this : DEL and BACKSPACE. You can use Fn-Delete to perform forward deletion while the button Delete acts as Backspace.
7. Related Messages~在Mail裡使用的快速鍵~方便回信時用
快速鍵 : Command-Shift-K
Note. Selects all related messages in the same mailbox.
8. Open Address in New Tab~在新分頁中開啟網址
快速鍵 : Command-Enter
Note. While highlighting address bar, pressing this shortcut will bring up new tab of that selected address.
9. Google Search Box~在Safari與Firefox瀏覽器中可將游標快速移至搜尋bar中(按Command-L是前往網址列)
快速鍵 : Command-Option-F
Note. Quickly jumps your cursor to Google Search Box. Saving your mouse click as well as your precious ticks of seconds.
10. Zoom~放大或縮小螢幕的功能(也可利用Control+滑鼠滾輪,但需要在偏好設定中開啟此功能)
快速鍵 : Command-Option-[+] (Zoom In) or Command-Option-[-] (Zoom Out)
Note. Zoom in/out your display; making tiny objects looks huge.
轉載原文於此:Unveiling 10 Hidden OS X Shortcuts
-----EOF-----
其实第一个输入苹果的快捷键真的挺好玩。。。
本来还没有发现。但是这两天发现访问量越来越少,仔细检查了一下。原来是RSS输出有问题。
于是准备重新检查代码一点点的往下看了。事实上这一块我并没有动过,但突然间数据就从8-29号开始就没有了。真TMD纠结啊。
哎。又得看代码了。否则我的访问量会逐日下降了。果然有些东西自己不盯着的时候,总会出一些奇怪的问题的。。妖怪啊。
顺便说一个题外话:app store中的“聪明鱼”还是有点意思的。老婆玩了之后开始慢慢的上瘾了。
-------------------------
原来是我自己的偷懒导致的。图片直接存到数据库了,然后导致输出非常大。一个RSS超过了2M,真纠结
小孩子上了几天学,开始有厌学情绪了,上学前会哭个半天不肯去。直到学校的老师把他接进去才肯停。然后说今天不想外婆走,于是对老师说。我要和外婆有几句话讲。。。。但老师不理他还是把他带进了教室。
希望他慢慢适应吧。总是需要一个过程的。
这两天还是在看flipboard的JS代码,几乎看完了。明天开始出Demo了。如果再不出demo什么的。估计会被人砍死了。。
再,发现readabiltity还是有用武之地的。至于用在哪里我暂时不说,嗯,确实有意思。。。。
再,arc90团队的一些想法还是不错的。。。。
再,中午有个法国人到公司来,突然让我想起上次和一法国人交流,我说英语他听不懂,他说英语我也听不懂,最后我说中文,他全懂了。哦,卖糕的。。。。
再,给几个同事布置了点小题目,希望他们下周能够做出来,题目都不难,都是一些基础题,但想拿高分,还是得有一定基础。
再,最近开始用苹果,等项目告一段落后就开始尝试用xcode开发了
顺便,想知道苹果上有没有类似sqlog这类的程序。否则我每次运行sqlog都得跑到虚拟机下面,虽然内存占的不多,但总不爽。。。
e4e504aa
nodeType的取值还是会经常用到的,但一般我们只用1和3,找了一下资料,1和3的含义是什么,才发现,原来是这样的。【部分资料来自:http://www.impng.com/web-dev/element-nodetype-values.html】
整数 |
常量 |
1 |
ELEMENT_NODE,普通元素节点,如<html>,<p>,<div>,<span>,<img> |
2 |
ATTRIBUTE_NODE,元素属性 |
3 |
TEXT_NODE,文本节点 |
4 |
CDATA_SECTION_NODE,即<![CDATA[ ]]> |
5 |
ENTITY_REFERENCE_NODE,实体引用,如& |
6 |
ENTITY_NODE,实体,如<!ENTITY copyright “Copyright 2010, impng. All rights reserved”]> |
7 |
PROCESSING_INSTRUCTION_NODE,PI,处理指令,如<?xml version=”1.0″?> |
8 |
COMMENT_NODE,注释<!– –> |
9 |
DOCUMENT_NODE,根节点,即document.nodeType |
10 |
DOCUMENT_TYPE_NODE,DTD,文档类型<!DOCTYPE > |
11 |
DOCUMENT_FRAGMENT_NODE,文档片段 |
12 |
NOTATION_NODE,DTD中定义的记号 |
需要注意的是,在IE下会直接跳过HTML中的空格/Tab/换行,而Firefox下空格会认为是一个节点,因此,对类似节点取nextSibling或previousSibling时,需要判断是否是元素节点。所以。要取某个节点下面的文字时,必须是类似这样的写法。
JavaScript代码
- function L(a) {
- var b = "";
- for (a = a.firstChild; a; a = a.nextSibling){
- if (a.nodeType === 3){
- b += a.nodeValue;
- } else if (a.nodeType === 1){
- b += L(a);
- }
- }
- return b
- }