2016年12月29日星期四

Github 提交后 calendar 不显示 contributions 的问题

用 Github 的一大 H 点就是看着个人首页 calendar 的绿点从无到有从浅变深从星星之火到可以聊原,问题来了,我的 calendar 两三个星期没有显示任何更新了,可是我明明这段时间提交了不少,回想了一下以前也遇到过这样的问题。

是问题就要解决它!
颠三倒四
一般是因为本地的邮件地址跟 Github 个人资料里不一样导致的。

在某本地仓库里git show一下,会看到author 是本机电脑名peikun,邮件是peikun@ZHOU.local,这完全不合适嘛。得修改,

git config user.name yourname
git config user.email zpkhhx#gmail.com

就可以修改当前仓库的作者信息。全局的可以直接加上--global 参数,


git config --global user.name yourname
git config --global user.email zpkhhx#gmail.com

对本地的更改再次提交到 github 上,首页上那一抹绿就回来了...有点怪


2016年12月28日星期三

mac os 配置 prolog

AI 作业开玩有趣的prolog,记录下配置 mac os 10.12.2 环境下配置 prolog 吧。


  • SWI-Prolog GUI

主流是安装 SWI-Prolog,链接在这里,注意这里是开发版的,亲测稳定版对本机(10.12.2)支持不好,内置 terminal 莫名其妙黑屏。安装开发版,你也可能需要安装XQuartz(X11).

安装就绪,打开SWI-Prolog,载入测试文件,

?- ['/..../family.pl'].
输出 true,即是成功。


  • Terminal Prolog

作为程序猿,APP的 GUI显然不能显示我们的逼格,大多情况下还是需要请出 Terminal。

依赖SWI-Prolog 修改环境变量是一个办法,brew 安装是一个更普世的办法,

Simply go to terminal window and type in:
brew tap homebrew/x11
after the above command executes, enter:
brew install swi-prolog --HEAD
and now swipl should work:
Maryams-MacBook-Pro:~ maryam$ swipl
returns
Welcome to SWI-Prolog (Multi-threaded, 64 bits, Version 7.3.3)
Copyright (c) 1990-2015 University of Amsterdam, VU Amsterdam
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software,
and you are welcome to redistribute it under certain conditions.
Please visit http://www.swi-prolog.org for details.

For help, use ?- help(Topic). or ?- apropos(Word).
Yay! ready to go. Let's test this:
?- ['/..../family.pl'].

true.


  • Emacs prolog
以前用 OCaml 的时候,接触了 Emacs这一神器,对于 Prolog 我们依然可以信赖它,参考教程在这里


  1. Download the file prolog.el from https://bruda.ca/emacs/prolog_mode_for_emacs and save it in your load-path so that Emacs can find it.
  2. Optionally, you can byte-compile prolog.el for better performance. Load prolog.el into Emacs and do M-x byte-compile-file RET.
  3. Add the following lines to ~/.emacs (~/_emacs on Windows):
    (autoload 'prolog-mode "prolog" "Major mode for editing Prolog programs." t)
    (add-to-list 'auto-mode-alist '("\\.pl\\'" . prolog-mode))
    Where is ~/_emacs?
    ~ is a shortcut for the home directory, on Windows it is system and language specific. It may be for example C:\ orC:\Dokumente. The best way to find "~" is: select "Files->Open.." and enter "~". Then Emacs prints the directory name and contents.
  4. Customize the Prolog mode. The following page explains how to enable electric indentation, syntax checking and PceEmacs-style comments: https://www.metalevel.at/pceprolog/
  5. ediprolog allows you to interact with SWI-Prolog in all Emacs buffers. You can quickly consult buffers and regions, and run queries that are embedded in your source files. ediprolog is available from: https://github.com/triska/ediprolog







2016年7月7日星期四

Win10 manually installation

Copy 'boot', 'bootmgr' and 'sources' to root C:/ ,

Run cmd at WinPE, then run commands 'c:\boot\bootsect.exe /nt60 c:' and receie 'successful'

Restart PC and installation will be run.

2016年6月16日星期四

Outlook全局通讯录(Global Adress Book)无法同步引出的一系列问题

公司有自己的exchange邮件服务器,用户一般用Outlook收发邮件、日程表、安排会议。有若干同事一直在反映,无法在通讯录里看到公司的全局通讯录,平时手工添加甚是麻烦。

I tried download Address Book(at SEND/RECEIVE->Send/Receive Groups->Download Address Book), but it didn't work.

Then I tried this,

1. First backup data file, remove actually account in Outlook then re-add it, not manually add but automatically.

2. Install Outlook Certificate which locates on M:\IT_Public\Programs\Outlook Certificate.

3. Re-start Outlook and import backup data file, problem is solved!

Before, in file->info->account settings, there isn't Delegate Access, Download Address Book or Manage Mobile setting choice. Right now, it all has.

Though the problem is solved, I'm still not sure it caused by certificate or during add account procedure. I guess the former administrator didn't find Outlook certificate at time so he added account manually. In my way, I added certificate during adding account automatically procedure.

It's not a problem, give me root, I can solve everything. I won't tell you that I have no permission to log in exchange server.

-.-

2016年6月10日星期五

Alternate access URLs have not been configured (SharePoint 2016)

Applies to: SharePoint Server 2013, SharePoint Foundation 2016
Summary: Learn how to resolve the SharePoint Health Analyzer rule "Alternate access URLs have not been configured."
Rule Name: Alternate access URLs have not been configured.
Summary: A default zone URL must not point to the computer name of a Web front-end server. Because this installation has more than one Web front-end server, an incorrectly configured default zone URL can result in a variety of errors, including incorrect links and failed operations.
Cause: A default zone URL is pointing to the computer name of a Web front-end server.
Resolution: Change the default zone URL to a URL that differs from the computer name of any Web front-end server.
  1. Verify that the user account that is performing this procedure is a member of the Farm Administrators group.
  2. On the Central Administration home page, in the System Settings section, click Configure alternate access mappings.
  3. On the Alternate Access Mappings page, on the Alternate Access Mapping Collection menu, click Change Alternate Access Mapping Collection.
  4. In the Select An Alternate Access Mapping Collection dialog box, click the alternate access mapping collection for which you want to change the default zone URL.
  5. On the Alternate Access Mappings page, click Edit Public URLs.
  6. On the Edit Public Zone URLs page, in the Default text box, type a new default zone URL that differs from the computer name of any Web front-end server, and then click Save.

2016年6月8日星期三

妙用excel做字符串的拼接处理

今日做前端开发,很费力的要把将近两千行的数据item预载入在线表格中,需要特定的数据格式,形如,

data = [
  [1, "string", ***],
  [2, "string", ***],
  ....
]

当前已有的是item_num和item_name目录。刚开始的思路是将其全部复制进txt文本,形如
如下格式,然后用python做字符串的拼接处理。

item_num, item_name
item_num, item_name
....

发现小问题了,每一行后的\n都需要split消除;若想得到List的形式,又会引入新的“”;拼接为单一的一个string不是很友好...果断舍弃,扔一边儿去接着看js各种轮子。

这时,手头的excel灵光乍现!!

1.首先将item_num和item_name分别复制进excel中,得到两列。
2.插入列,填补内容
3.同一行若干个单元格合并,小小的公式“=A2&B2&C2&D2&E2”



合并之后,如图


末列的单元格就是我想要的数据子格式啦。全部复制进[]中,我的data预载入数据就有了,


最终web端在线表格有了预载入的数据,如图,



再次为我的帅气和机智叹服。

2016年6月3日星期五

Outlook full problem

A couldn't find her old mail which has been archived and moved by B.

So I help her to export the history Outlook data, file -> Open&Export -> Open Outlook Data File -> locate and select target data file, then it's ok.

************Outlook full problem***********************

users always meet problem that outlook is full because user's space is only 1G, so AutoArchive is necessary.

To solve this problem, I find an idea,

1. new local data file at Account Settings, which named local_backup, of course, we could also new subfolder named inbox/Drafts/@/#$#
2. archive
   - AutoArchive, for inbox or sent items, we have choices at AutoArchive to delete old mails according to the time and AutoArchive them to local data file
   - Manual, whenever our mailbox is full we could select them to move into local_backup and then delete them
3. in local_backup folder, we could find what we need. One more important, search All Outlook items or All Mailboxes is very helpful.

2016年5月30日星期一

windows下为python安装*.whl

给我一个Terminal,我可以创造一个世界。

给我一台windows,我只能活在盖茨的世界里。

环境win7 64bit,python2.7,怎么安装.whl的拓展包呢?什么环境变量,pip的都不用管了,只需要cmd下一句话,

python -m pip install ***********.whl


就可以啦

2016年5月9日星期一

python遍历文件夹小结

下面来小结一下Python遍历文件夹的几种方法。

方法1:使用os.listdir
import os
for filename in os.listdir('c:\windows'):
    print filename

本结果直接输出当前根目录下的所有名字,即文件夹名和文件名,并没有进入子文件夹,同时并不包括文件路径,格式如下,

dsdkljsalkdjsalk.txt
ndskdkewjdkj.doc
folder1
folder2

- 对于想输出特定目录下的文件名/文件夹名,可以再加入条件判断,

os.path.isfile(root+filename)
os.path.isdir(root+filename)

这样加以筛选就可以只输出当前路径下所有文件名,或者当前路径下所有文件夹名。

- 如果你想按照特定顺序排列,如modified或者created time,需对当前排序。

假定当前的所有文件名都存在在某list1内,形如,

    for filename in os.listdir(folder):
        if(os.path.isfile(folder+filename)):
            list1.append(os.path.join(folder, filename))

    sorted_list1 =  sorted(matches, key=os.path.getmtime)

只需在sorted里加入key即可,这里的key是os.path.getmtime,文件的更改时间,
os.path.getatime是最近访问时间,os.path.getctime是创建时间。

*注意,这里的list1中os.path.join()方法用于组建新的路径名,我们除了filename,还加入了这些文件的当前路径。这里的folder路径不能去掉,否则笨蛋的程序凭借光杆文件名不会定位到我们的文件位置。

- 问题又来了,我们得到的经过排序的sorted_list1里还包含了路径名,这样大煞风景,怎么办呢?  用split!

    for name in sorted_matches:
        name_complet.append(name.split("/")[-1])

这里巧妙地割出-1个“/”的字符串,即左起第一个“/”前的字段,就是我们的完整文件名啦。

 
方法2:使用glob模块,可以设置文件过滤

import glob
for filename in glob.glob('c:\windows\*.exe'):
    print filename

本方法很方便筛选特定格式的文件。
 

方法3:通过os.path.walk递归遍历,可以访问子文件夹

import os.path
def processDirectory ( args, dirname, filenames ):
    print 'Directory',dirname
    for filename in filenames:
        print ' File',filename
 
os.path.walk('c:\windows', processDirectory, None )

这是使用最多的方法,可以递归进入子文件夹,从而实现某目录所有文件遍历的效果。
 
方法4:非递归

#!/bin/python
#
#site:www.jbxue.com
import os
for dirpath, dirnames, filenames in os.walk('c:\\winnt'):
    print 'Directory', dirpath
    for filename in filenames:
        print ' File', filename



2016年4月28日星期四

Rails app redmine 出现“Incomplete response received from application” 问题

搭建好的Redmine服务器,才运转两天就出问题,project里new issue的时候蹦出“Incomplete response received from application”的错误网页。真是费脑子啊。

万能的stackflow告诉我这是rails常见的错误,核心问题是secret token没配置好。这是rails应用经常出现的问题,故本文对rails应用有普适性。

缺少了production所必须的secret token, 那就生成好了。在这里,先说下它是干嘛的,

This step generates a random key used by Rails to encode cookies storing session data thus preventing their tampering.
Generating a new secret token invalidates all existing sessions after restart.

得当当前应用会话(标签页)重启/关闭的,secret token是用来解析cookies来防止随便访问和随便篡改的,验证通过,我才能对服务器里的数据修改(增减,在这里对应的是project/issue的新建)

说说解决方案,

1. 服务器上定位到我们的rails应用redmine文件夹,rake secret生成密钥

2. redmine/config 文件夹下新建secret.yml,格式如下,

development:
  secret_key_base:
 
test:
  secret_key_base:
 
production:
  secret_key_base: **********************************


在production的secret_key_base下补充上我们的密钥。这里暂时忽略development和test,我们是应用,不是二次开发,哈哈

这里的复制粘贴不是那么友好,我们也可以这样来省事儿,

development:
  secret_key_base:
 
test:
  secret_key_base:
 
production:
  secret_key_base: <%= ENV["SECRET_KEY_BASE"] %>

保存退出,重启服务,我这么懒直接重启的服务器。

bug不见啦。

References,
1. http://stackoverflow.com/questions/29241053/incomplete-response-received-from-application-from-nginx-passenger
2. http://guides.rubyonrails.org/upgrading_ruby_on_rails.html#config-secrets-yml

2016年4月27日星期三

解决一次python报错ValueError: list.remove(x): x not in list的问题

公司里勤劳帅气却老是走神的小周同志又来了!

这次是这样的,比较两个规模比较大的List A和B, A中的元素e1前几个字符跟B中的元素e2前几个字符(形如thesamewords_______)匹配的话,输出e1到一新的List,同时对A和B进行更新(删除)。注意重复的情况。

思路很简单喽,两层for循环,匹配字符串前N位,if语句判断是否匹配,匹配的话加入新的list同时更新原来的List。简单写的代码如下,


l1 = ['aaaaaad', 'COFREP-B00000390-2015-05-SLCRXX-00-L-N--.zip', 'c', 'd']
l2 = ['aaaaaac', 'sada', 'dadada', 'da', 'di']
for e1 in l1:
    for e2 in l2:
        if e1[:6] == e2[:6]:
            l1.remove(e1)
            l2.remove(e2)
            l3.append(e1)
print l1
print l2

print l3

结果很理想,如下,

['COFREP-B00000390-2015-05-SLCRXX-00-L-N--.zip', 'c', 'd']
['sada', 'dadada', 'da', 'di']
['aaaaaad']

[Finished in 0.1s]

小测试完毕,更新list数据源,重新运行,就报错啦,唯一有用的一行是,
ValueError: list.remove(x): x not in list

测试多组数据,还是没有解决,跟HR美女姐姐吃饭去了。重点是,吃完饭回来,短短几分钟就找到了bug所在,到底还是美女的力量大!

说说我是怎么测试找出来的吧——————控制变量法,小学就学过的,

保持l1不变,更改l2的数据。简例中匹配的是aaaaaa___,因此l2中的aaaaaac被删除了,l1中的aaaaaad也被删除了,l3中有了aaaaaad。当l2 =  ['aaaaaac', 'aaaaaae', 'sada', 'dadada', 'da', 'di']时,即出现第二个aaaaaa___时,如上的错误再次出现了!兴奋!

用脚指头想象一下,l1[0]匹配到l2[0]的时候,分别对其执行remove(e1)和remove(e2)操作(l1[0]和l2[0]都被删除了),但是此时第二层loop还没有结束,又匹配到了l2[1](aaaaaae),此时会再次对l1执行操作remove(e1),一个完美的扑空!l1中已经没有删掉的e1了,因此报错。

To solve this bug, just one finger! may be five,

break

在if层末尾加上break结束语句就好啦!

一次多么絮絮叨叨又二逼的简单错误。


解决python出现unindent does not match any outer indentation level的问题

用Sublime Text写python,轻便爽快之余,少了些许pycharm的贴心。想起一个贴切的比喻,编辑器就是镰刀斧头,轻装上阵只管拿它来开天辟地;IDE编程好比操纵一台台精妙齐全的机器,成熟和曼妙不在其中你是不会懂。

这次遇到的问题是出现unindent does not match any outer indentation level,谷歌告诉我大多数情况下都是tab和space惹的祸,我们都知道python离开了对齐就是一堆乱码。所以呢,我们要统一度量衡!

Sublime下, View -> Indentation -> Convert Spaces to Tabs/Convert Tabs to Spaces

调教一下,重新C+B,发现问题就解决啦。

2016年4月25日星期一

映射网罗驱动器解决python遍历局域网某服务器目录的问题

遇到一个问题,windows下写python脚本需要遍历局域网内某windows server目录,找了一通的python远程桌面方案,繁琐杂乱不友好。正当午后昏昏欲睡的时候,灵机一动!

公司有个服务器专门为共享资源服务器,在每一台PC上都通过影射网络驱动器来访问,如此相当于是一个本地磁盘位置,安全快捷方便省心效率高。我为什么不用呢!

1. 登录RDC,将待遍历目录共享,我直接把一个磁盘都共享了。磁盘右键->共享即可

2. 打开本地我的电脑,Map network drive (映射网络驱动器)选项 -> 选择驱动器盘符和远端位置 例,\\192.168.1.1\D,勾选Reconnect at logon选项,以便每次登录自动链接

就是这样了。完完全全把远端的目录当作本地目录来用。

2016年4月22日星期五

配置Redmine服务器遇到的一些问题总结

boss把配置失败的redmine扔给我,让我重新配置,撂下狠话,大不了你把debian重装下,于是我开始了拧巴的调试/配置/Debug/擦屁股之路,遇到很多问题,ruby/rails的坑很多,挨个写下来吧。注意,本机环境为VM虚拟服务器里的debian

1. gem install rails 失败

具体的报错信息如下,

 ERROR: Failed to build gem native extension.

        /usr/bin/ruby1.9.1 extconf.rb 
checking if the C compiler accepts ... yes
Building nokogiri using packaged libraries.
checking for gzdopen() in -lz... no
zlib is missing; necessary for building libxml2
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
    --ruby=/usr/bin/ruby1.9.1
    --help
    --clean
    --use-system-libraries
    --enable-static
    --disable-static
    --with-zlib-dir
    --without-zlib-dir
    --with-zlib-include
    --without-zlib-include=${zlib-dir}/include
    --with-zlib-lib
    --without-zlib-lib=${zlib-dir}/lib
    --enable-cross-build
    --disable-cross-build
首先提示Build gem native extension失败,接下来的检查各种依赖环境/包时,可以看到C compiler-yes,gzdopen()-no,重要提示来了,“zlib is missing; necessayr for building libxml2....”很显然,缺少libxml2环境,那装上不就得了,

    apt=get install zlib1g-dev
然后重新gem install rails,刷刷地一路successful.

2. bundle install --without development test失败
报错提示安装gem install rmagick,然后有错误如下,

Can't install RMagick 2.13.1. Can't find Magick-config in /Users/jjdevenuta/.rvm/gems/ruby-1.9.2-head@rails3/bin:/Users/jjdevenuta/.rvm/gems/ruby-1.9.2-head@global/bin:/Users/jjdevenuta/.rvm/rubies/ruby-1.9.2-head/bin:/Users/jjdevenuta/.rvm/bin:/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/git/bin:/usr/X11/bin

*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
那么跟之前解决方案类似,缺啥补啥,再装上缺少的包!
apt-get install libmagickwand-dev imagemagick

就可以了,我在stockoverflow上看到一段话,对这类问题做了一个很好的归纳总结,摘录如下,

When building native ruby gems, sometimes you'll get an error containing "ruby extconf.rb". This is often caused by missing dev libraries for the gem you're installing, or even ruby itself. Do you have apt installed on your machine? If not, I'd recommend installing it, it's a quick and easy way to get a lot of dev libraries.

一般请款修改出现此类问题是因为缺少相应的dev包,或者ruby本身有问题,解决方案就是安装相应包的dev。

再次执行,bundle install --without development test,成功啦。





















2016年4月11日星期一

javascript必知必会之prototype

离考试还有半个小时,温故知新js的prototype,遇到此文,分享之. 原文链接

但是最后讲的函数自身声明的方法与prototype添加的方法,比较不是特别清楚.

javascript必知必会之prototype

本博客所有内容采用 Creative Commons Licenses 许可使用. 引用本内容时,请保留 朱涛出处 ,并且 非商业 .
点击 RSS 进行订阅.(推荐使用 google reader, 如果你的浏览器不支持直接订阅, 请直接在 google reader 中手动添加).

摘要

本系列博文主要谈一些在 javascript 使用中经常会混淆的高级应用,包括: prototype, closure, scope, this关键字. 对于一个需要提高自己javascript水平的程序员,这些都是必须要掌握的.
本节主要介绍prototype.

起由

最近在做一个项目,里面大量地使用 javascript 作为页面的动态生成脚本, 使用 json 与服务器进行通信. 在读之前遗留的代码时, 经常会弄不清楚, 作用域, this关键字在当前context下的指向等,于是便开始专门学习了 相关的知识,记录下来与大家分享.
下面的内容中会有一些代码,建议大家也去尝试修改和理解,这样更容易掌握. 点击 这儿 下载所涉及到的源码.

prototype

javascript 是一种 prototype based programming 的语言, 而与我们通常的 class based programming 有很大 的区别,我列举重要的几点如下:
  1. 函数是first class object, 也就是说函数与对象具有相同的语言地位
  2. 没有类,只有对象
  3. 函数也是一种对象,所谓的函数对象
  4. 对象是按 引用 来传递的
那么这种 prototype based programming 的语言如何实现继承呢(OO的一大基本要素), 这也便是 prototype 的由来.
看下面的代码片断:
function foo(a, b, c)
{
return a*b*c;
}
alert(foo.length);
alert(typeof foo.constructor);
alert(typeof foo.call);
alert(typeof foo.apply);
alert(typeof foo.prototype);
对于上面的代码,用浏览器运行后你会发现:
  1. length: 提供的是函数的参数个数
  2. prototype: 是一个object
  3. 其它三个都是function
而对于任何一个函数的声明,它都将会具有上面所述的5个property(方法或者属性).
下面我们主要看下prototype.
// prototype
function Person(name, gender)
{
this.name = name;
this.gender = gender;
this.whoAreYou = function(){//这个也是所谓的closure, 内部函数可以访问外部函数的变量
var res = "I'm " + this.name + " and I'm a " + this.gender +".";
return res;
};
}
// 那么在由Person创建的对象便具有了下面的几个属性
Person.prototype.age = 24;
Person.prototype.getAge = function(){
return this.age;
};
flag = true;
if (flag)
{
var fun = new Person("Tower", "male");
alert(fun.name);
alert(fun.gender);
alert(fun.whoAreYou());
alert(fun.getAge());
}
Person.prototype.salary = 10000;
Person.prototype.getSalary = function(){
return this.name + " can earn about " + this.salary + "RMB each month." ;
};
// 下面就是最神奇的地方, 我们改变了Person的prototype,而这个改变是在创建fun之后
// 而这个改变使得fun也具有了相同的属性和方法
// 继承的意味即此
if (flag)
{
alert(fun.getSalary());
alert(fun.constructor.prototype.age);//而这个相当于你直接调用 Person.prototype.age
alert(Person.prototype.age);
}
从上面的示例中我们可以发现,对于prototype的方法或者属性,我们可以 动态地 增加, 而由其创建的 对象自动会 继承 相关的方法和属性.
另外,每个对象都有一个 constructor 属性,用于指向创建其的函数对象,如上例中的 fun.constructor 指向的 就是 Person.
那么一个疑问就自然产生了, 函数对象中自身声明的方法和属性与prototype声明的对象有什么差别?
有下面几个差别:
  1. 自身声明的方法和属性是 静态的, 也就是说你在声明后,试图再去增加新的方法或者修改已有的方法,并不会 对由其创建的对象产生影响, 也即 继承 失败
  2. 而prototype可以动态地增加新的方法或者修改已有的方法, 从而是 动态的 ,一旦 父函数对象 声明了相关 的prototype属性,由其创建的对象会 自动继承 这些prototype的属性.
继续上面的例子:
flag = true;
// 函数内部声明的方法是静态的,无法传递的
Person.school = "ISCAS";
Person.whoAreYou = function(){
return "zhutao";
};//动态更改声明期的方法,并不会影响由其创建的对象的方法, 即所谓的 静态
if (flag)
{
alert(Person.school);
alert(fun.school);//输出的是 "undefined"
alert(Person.whoAreYou()); //输出 zhutao
alert(fun.whoAreYou()); // I'm Tower and I'm a male.
}
Person.prototype.getSalary = function(){
return "I can earn 1000000 USD";
};
if (flag)
{
alert(fun.getSalary());//已经继承了改变, 即所谓的 动态
}
既然有函数对象本身的属性, 也有prototype的属性, 那么是由其创建的对象是如何搜索相应的属性的呢?
基本是按照下面的流程和顺序来进行.
  1. 先去搜索函数对象本身的属性,如果找到立即执行
  2. 如果1没有找到,则会去搜索prototype属性,有2种结果,找到则直接执行,否则继续搜索 父对象 的 父对象 的prototype, 直至找到,或者到达 prototype chain 的结尾(结尾会是Object对象)
上面也回答如果函数对象本身的属性与prototype属性相同(重名)时的解决方式, 函数本身的对象 优先 .
再看一个多重prototype链的例子:
// 多重prototype链的例子
function Employee(name)
{
this.name = "";
this.dept = "general";
this.gender = "unknown";
}
function WorkerBee()
{
this.projects = [];
this.hasCar = false;
}
WorkerBee.prototype = new Employee; // 第一层prototype链
function Engineer()
{
this.dept = "engineer"; //覆盖了 "父对象"
this.language = "javascript";
}
Engineer.prototype = new WorkerBee; // 第二层prototype链
var jay = new Engineer("Jay");
if (flag)
{
alert(jay.dept);    //engineer, 找到的是自己的属性
alert(jay.hasCar);  // false, 搜索到的是自己上一层的属性
alert(jay.gender);  // unknown, 搜索到的是自己上二层的属性
}
上面这个示例的对象关系如下:
http://farm3.static.flickr.com/2585/3933273719_ccab4562d2.jpg

结论

javascript 的prototype给语言本身增加了很强的灵活性,但与 class based programming 相比整个思维逻辑还是有很大的不同,所以需要更多地思考和揣摩.
而 javascript是披着c语言外衣的函数式语言 的理解自然也需要更多地思考.
下一节我会继续讨论下 javascript 的另一个重要而且比较容易弄错的知识 closure.
欢迎大家留言讨论.