Uncategorized

Install ffmpeg video streaming server on Centos

 

 

http://www.mysql-apache-php.com/ffmpeg-install.htm

How to Install FFmpeg in Linux ~The Easy Way~

FFmpeg is so important if you are planning to run a video website with streaming with conversion of video files to different video formats although you might want to upgrade to dedicated server hostingbecause it takes a huge amount of bandwidth. This tutorial is intended for Centos/Redhat versions of Linux where any novice user can install ffmpeg without compiling the source which is a more traditional way of installing the FFmpeg software on linux servers. In this tutorial i will show you the easy way to install ffmpeg and ffmpeg-php (php extension) with just yum rather than compiling ffmpeg from source files.

 

FFmpeg (http://ffmpeg.mplayerhq.hu)
Mplayer + Mencoder (http://www.mplayerhq.hu/design7/dload.html)
Flv2tool (http://inlet-media.de/flvtool2)
Libogg + Libvorbis (http://www.xiph.org/downloads)
LAME MP3 Encoder (http://lame.sourceforge.net)
FlowPlayer – A Free Flash Video Player – http://flowplayer.org/

Installing FFMpeg

yum install ffmpeg ffmpeg-devel

If you get package not found, then you will need to add few lines in the yum repository for dag packages installation. Create a file named dag.repo in /etc/yum.repos.d with the following contents on it

[dag]
name=Dag RPM Repository for Red Hat Enterprise Linux
baseurl=http://apt.sw.be/redhat/el$releasever/en/$basearch/dag
gpgcheck=1
enabled=1

then

yum install ffmpeg ffmpeg-devel

If everything is fine, then the installation should proceed smoothly. If not you will get something like warning GPG public key missing .

Common Errors

To fix rpmforge GPG key warning:

rpm -Uhv http://apt.sw.be/redhat/el5/en/i386/rpmforge/RPMS/rpmforge-release-0.3.6-1.el5.rf.i386.rpm

For more information refer to this faq depending on Centos version

Missing Dependency Error:

If you get missing dependency error like shown below, in the middle of ffmpeg installation

Error: Missing Dependency: libc.so.6(GLIBC_2.4) is needed by package ffmpeg
Error: Missing Dependency: libtheora.so.0(libtheora.so.1.0) is needed by package ffmpeg
Error: Missing Dependency: rtld(GNU_HASH) is needed by package ffmpeg
Error: Missing Dependency: libc.so.6(GLIBC_2.4) is needed by package imlib2
Error: Missing Dependency: rtld(GNU_HASH) is needed by package a52dec
Error: Missing Dependency: rtld(GNU_HASH) is needed by package imlib2
Error: Missing Dependency: rtld(GNU_HASH) is needed by package gsm
Error: Missing Dependency: libc.so.6(GLIBC_2.4) is needed by package x264
Error: Missing Dependency: rtld(GNU_HASH) is needed by package xvidcore
Error: Missing Dependency: libc.so.6(GLIBC_2.4) is needed by package lame
Error: Missing Dependency: libc.so.6(GLIBC_2.4) is needed by package a52dec
Error: Missing Dependency: rtld(GNU_HASH) is needed by package faad2
Error: Missing Dependency: rtld(GNU_HASH) is needed by package x264
Error: Missing Dependency: rtld(GNU_HASH) is needed by package lame
Error: Missing Dependency: libc.so.6(GLIBC_2.4) is needed by package xvidcore
Error: Missing Dependency: libc.so.6(GLIBC_2.4) is needed by package faac
Error: Missing Dependency: libc.so.6(GLIBC_2.4) is needed by package faad2
Error: Missing Dependency: libgif.so.4 is needed by package imlib2
Error: Missing Dependency: rtld(GNU_HASH) is needed by package faac
Error: Missing Dependency: libc.so.6(GLIBC_2.4) is needed by package gsm
Error: Missing Dependency: libpng12.so.0(PNG12_0) is needed by package imlib2
Error: Missing Dependency: rtld(GNU_HASH) is needed by package libmp4v2
Error: Missing Dependency: libc.so.6(GLIBC_2.4) is needed by package libmp4v2

then most commonly you have GLIB 2.3 installed instead of GLIB 2.4 version. To check the current GLIB version installed on your server. just use

yum list glib*

and it should list the latest GLIB package version.

The reason i was getting this error was my rpmforge packages was pointed to centos 5 versions instead of centos 4.6.

To fix dependency error:

To fix this error, you might need to check your rpmforge packages compatible to the release of your existing CentOS version.
Check the file /etc/yum.repos.d/rpmforge.repo and it should look like for Centos 4.6(Final). If you have lines like http://apt.sw.be/redhat/el5/en/mirrors-rpmforge you might need to make changes to the rpmforge.repos like shown below

Note: Backup the original rpmforge.repo file before you edit its content.

[rpmforge]
name = Red Hat Enterprise $releasever – RPMforge.net – dag
#baseurl = http://apt.sw.be/redhat/el4/en/$basearch/dag
mirrorlist = http://apt.sw.be/redhat/el4/en/mirrors-rpmforge
#mirrorlist = file:///etc/yum.repos.d/mirrors-rpmforge
enabled = 1
protect = 0
gpgkey = file:///etc/pki/rpm-gpg/RPM-GPG-KEY-rpmforge-dag
gpgcheck = 1

To know what linux type and version you are running

cat /etc/redhat-release

Once this is done, do again yum install ffmpeg.

This trick resolved the problem in my linux box running Centos 4.6 and this is the only way i found to install ffmpeg using yum.

To check the FFmpeg working:

Finally, check the ffmpeg whether it is working or not.

> ffmpeg
> ffmpeg -formats
> ffmpeg –help
// This lists path of mpeg, its modules and other path information

ffmpeg -i Input.file Output.file

To check what audi/video formats are supported

ffmpeg -formats > ffmpeg-format.txt

Open the ffmpeg-formats.txt to see the ooutput

D means decode
E means encode
V means video
A means audio
T = Truncated

Install FFMPEG-PHP Extension

FFmpeg-php is a very good extension and wrapper for PHP which can pull useful information about video through API interface. Inorder to install it you will need to download the source file and then compile and install extension in your server. You can download the source tarball : http://ffmpeg-php.sourceforge.net/

wget /path/to/this/file/ffmpeg-php-0.5.2.1.tbz2

tar -xjf ffmpeg-0.5.2.1.tbz2

phpize

./configure
make
make install

Common Errors

1. If you get command not found error for phpize, then you will need to do yum install php-devel

2. If you get error like “ffmpeg headers not found” while configuring the source.

configure: error: ffmpeg headers not found. Make sure ffmpeg is compiled as shared libraries using the –enable-shared option

then it means you have not installed ffmpeg-devel packages.

To Fix: Just install ffmpeg-devel using

yum install ffmpeg-devel

3. If you get an error like shared libraries not found problem and the program halts in the middle, then you must specify the ffmpeg installed path explicitly to the ./configure.

configure: error: ffmpeg shared libraries not found. Make sure ffmpeg is compiled as shared libraries using the –enable-shared option

To Fix:

1. First find out the ffmpeg path with ffmpeg –help command. The prefix default path should be like/usr/local/cpffmpeg
2. Configure the FFmpeg-php with –with-ffmpeg option

./configure –with-ffmpeg=/usr/local/cpffmpeg

That should resolve the problem!

Editing PHP.INI

Once you have done that without any problems then you will see the php extension file/usr/local/lib/php/extensions/no-debug-non-zts-20060613/ffmpeg.so and you will need mention that extension in php.ini file

nano /usr/local/lib/php.ini

Put the below two lines at the end of the php.ini file

[ffmpeg]
extension=ffmpeg.so

Then restart the server service httpd restart

To check whether ffmpeg enabled with php, point your browser to test.php file. It should show the confirmation of installed ffmpeg php extension

// #test.php

<?php

phpinfo()

?>

If any case the ffmpeg does not show in the phpinfo() test make sure that php.ini path to ffmpeg.so is correct. Still the problem occurs, the reason could be you might be using older versions of ffmpeg-php which is buggy. Just download the latest version of ffmpeg-php source then compile it.

Installing Mplayer + Mencoder

Just issue the following yum commands to install the rest of the packages.

yum install mplayer mencoder

Installing FlvTool2

Flvtool2 is a flash video file manipulation tool. It can calculate metadata and can cut and edit cue points for flv files.

If you are on Centos 5 try yum install flvtool2 with dag repository and if you get package not found you will need to manually download and compile the flvtool2. You can download latest version of flvtool2 here: http://rubyforge.org/projects/flvtool2/

wget <url-link>

ruby setup.rb config
ruby setup.rb setup
sudo ruby setup.rb install

If you get command not found error, it probably means that you dont have ruby installed.

yum install ruby

Thats it! Once ffmpeg works fine with php extension, download a sample video, convert to .flv format in the command line and plug it to flowplayer to see it work on your web browser. Try also to download the video file offline and see whether the converted flv file works well with both audio and video.

Useful Links

FFmpeg (http://ffmpeg.mplayerhq.hu)
Mplayer + Mencoder (http://www.mplayerhq.hu/design7/dload.html)
Flv2tool (http://inlet-media.de/flvtool2)
Libogg + Libvorbis (http://www.xiph.org/downloads)
LAME MP3 Encoder (http://lame.sourceforge.net)
FlowPlayer – A Free Flash Video Player – http://flowplayer.org/

Install FFmpeg from Compiling Source (Tutorial Link)
Nice FFmpeg Installation Tutorial (click here)
Important Audio Codecs (http://www.mplayerhq.hu/DOCS/HTML/en/audio-codecs.html)
Common Errors & Fixes while Installing FFmpeg (click here)

You can also post comments in my blog.

 

Standard
Uncategorized

逻辑和计算机 zz

  逻辑和计算机

从原理上说,计算机是一个无比简单的东西,就是一个逻辑处理器,计算机所做的所有
工作最后都是转化成逻辑运算来执行的。所以,任何能进行基本逻辑运算(非,与,和
)的东西,都可以用来构成计算机。计算机的构想早在在17世纪就提出来了,不过只能
用机械方式。
第一个真正现代意义上的计算机是用电子管实现的,但是它的应用非常有限,庞大,奇
贵,速度慢,而且耗能巨大。还有一个致命的缺陷,就是可靠性好不了。
现在的CPU集成了几亿只器件,如果用电子管,意味着上亿个插件,上十亿个焊点,这
样复杂的东西没有办法保证质量,更不可能大规模生产。计算机的发展赖于集成电路的
进步。
计算机的广泛应用,以至于完全改变了人类的生活,其硬件基础是上个世纪前30年以爱
因斯坦为首的那一拨人做的,有了量子物理和相对论,才能有凝聚态物理,才能有集成
电路,接下来才可能有计算机,网络的广泛使用。
记得曾经在网上有人讨论爱因斯坦和爱迪生哪一个更牛,这实在有点过分,两个人完全
不在一个档次,而且差得很远。爱因斯坦是一个科学家,《维基百科》说也是一个思想
家,我以为不错,他奠定了现代物理学的基础,对人类产生了根本的影响,极大地改变
了人类的生活以及我们对这个世界的理解,《时代杂志》把他评为上个世纪最伟大的人
物,毫不过分。
爱迪生只是一个发明家,发明了白炽灯,留声机这一类应用的产品而以。他的那一套发
明的方法已经过时,产品也没有人用了。比如美国已经不生产白炽灯,将来的照明肯定
是用发光二极管,效率接近于完美,寿命极长,这也是建立在爱因斯坦的理论基础之上
的。
总的说来,科学家对人类的影响是最大的,永久的,什么政治家,帝国不过是过眼云烟
罢了。

计算机软件的基础是数理逻辑,它可以看成是上个世纪数学取得的最重要的进展,几乎
改变了数学的整个面貌。建立的时间和现代物理基本上在同时,计算机科学可以看成是
数理逻辑在这个领域的一个具体运用。当然,一般的“码工”可能用不着知道数理逻辑
,那是因为有人为他们弄出了某种计算机语言,但对于那些弄出语言的人,没有数理逻
辑作为基础是不可能。
这个问题这样来讲也许容易一点,计算机的界限在哪里。不能说计算机能做什么,因为
它能做的事太多了,只能说计算机不能做什么,或者说是人工智能的问题。这个词好像
容易引起误解,因为要严格定义人工智能就得定义什么是人的智力,或者思维,而人的
思维是一个无法定义的东西,我们弄不清楚。
这个问题得从数学方面来探究,因为计算机说到底是一个逻辑处理器,这是计算机的硬
件所决定的,无法改变,这个问题就就能变成:逻辑能干什么?
这个问题主要由三个人的工作而得以阐明,弗雷格,罗素,哥德尔。这是数学最奇妙的
一点,数学的一些基础研究在开始的时候,根本看不到有什么用处,只是一些游戏式的
东西,或者哲学问题。但是,后来的发展却使这些东西变得有极大的实用价值。那个时
候的人根本就不知道什么是现在的计算机。
弗雷格的名字恐怕大多数人都没有听说,但他却是数理逻辑的奠基人,被认为是亚里士
多德以后最伟大的逻辑学家。罗素有了集合论这个工具,在弗雷格的基础之上想要完成
一件无比宏伟的工作,想把全部数学的基础建立在逻辑的上面。当然,罗素并不是要为
计算机做什么,他不怎么不关心这种事,而是出自于一种哲学上的思考,这就是所谓的
奥卡姆剃刀。
在弗雷格之前,数学和逻辑可以说是分开的东西。如果数学是一个假设,逻辑是另一个
假设(不是所有的人都承认数学只是一个假设的,这个问题我在谈维特根斯坦时比较详
细地讨论过,这里不妨当做一个假设接受下来,并不影响下面的讨论),那么把它们变
成一个东西就有极大的价值,因为奥卡姆剃刀说:“若无必要,勿增实体”,少一个假
设,自然出错的可能将会减少,这可以说是科学的一个基本原则。当然,如果数学就是
反映了客观实在,那么更应该能够统一。
但是,罗素失败了,因为他发现了所谓的罗素悖论,到了哥德尔不完备定律做了结论,
那不可能成功,就像哥德尔所说:“有些事实被认知为真,但不必然可证。”当然,要
是数学不是必然可证的话,那么逻辑怎么能是数学的基础。虽然罗素失败了,但是这些
人的努力却极大地推动了数学和哲学的发展,可以认为构成了上个世纪数学和哲学的主
流,而且,他们的工作在后来就构成了计算机科学的基础。
图灵被广泛地认为是计算机科学之父:“图灵在他的重要论文《论可计算数及其在判定
问题上的应用》,对哥德尔1931年在证明和计算的限制的结果作了重新论述,他用现在
叫做图灵机的简单形式裝置代替了哥德尔的以通用算术为基础的形式语言。”《维基百
科》这段话大致说明了图灵和哥德尔的关系,图灵不过是把哥德尔的定律用在计算机上
(图灵机可以看成是一种理想计算机),这种一致性的背后就是图灵机和形式语言说到
底都是逻辑。
图灵最重要的工作是:“停机问题(halting problem)是逻辑数学中可计算性理论的
一个问题。通俗的说,停机问题就是判断任意一个程序是否会在有限的时间之内结束运
行的问题。该问题等价于如下的判定问题:给定一个程序 和输入 , 程序 在输入 下是
否能够最终停止。
艾伦•图灵在1936年证明了,一个可以解决停机问题的通用算法是不存在的。这
个证明的关键在于对计算机和程序的数学定义,这被称为图灵机。停机问题在图灵机上
是不可判定问题。这是最早提出的决定性问题之一。
用数学语言描述,则其本质问题为: 给定一个图灵机 T,和一个任意语言集合 S,是否
T 会最终停机于每一个 。其意义相同于可确定语言。显然任意有限 S 是可判定性的
,可数的(countable)S 也是可停机的。
停机问题本质是一阶逻辑的不自洽性和不完备性,类似的命题有理发师悖论、全能悖论
等。”(本篇所有引用都来自《维基百科》,例外注明)
这里的理发师悖论、全能悖论都是罗素悖论的另一些表达形式。

这里就我自己的理解来解释一下,你要计算机干一个活,必须要知道它能不能胜任,也
就是在有限的时间里能不能得到一个结果,不然的话,就是眼前一片黑,所谓理论的指
导作用就是这个意思,实际上就是要了解计算机一个什么东西,我想这一点的重要性不
难理解。
毫无疑问,语言是人类最重要,也是最伟大的工具,但是,仍然只是一个工具,用于人
与人之间的沟通。那么对于一个工具来说,最要紧的就是知道它能够做什么,也许更重
要的是要知道它不能做什么,比如说你知道汽车不能在水里开肯定比能开多快要重要得
多。在语言哲学家看来,过去哲学的荒谬之处就在于对语言泛用,而根本不知道语言的
局限性,就像他们一直在水里开汽车,还在宣称感觉好极了,而且还边开边领悟到了这
个世界的真谛。
语言哲学和停机问题是有关联的,它们都是要企图找到一条线,那些是做不到的事情,
一个是针对语言,另一个是针对计算机,而且都是以数理逻辑作为基础的,这一点也决
不是偶然的。
在维特根斯坦看来,我们真正能理解的,能够达到一致的东西都必须以逻辑作为基础,
因为逻辑是一个天生的东西,大家都是一样的。除此以外,达到一致是不可能的,就像
你不可能说清楚什么是漂亮。
如果我们认可维特根斯坦关于语言只能确实地表达逻辑结构,那么从计算机的角度来理
解语言就会容易一些。如果一些计算机的程序和数据库是一模一样,那么当然,对同一
个问题它们的结论也必然是同样的。所以也许可以说,人与人的不同就在于各自程序和
数据库并不一样,这个不一样可以认为是与遗传和早年的经历和教育有关,恐怕没有两
个人可能一模一样,所以说,人与人的不同是不可以避免的。用维特根斯坦的话来说,
人与人的不同就在于各自的原子命题不同,出发点不同,所以各人眼中的世界是不可能
一样的。
而哥德尔告诉我们,在逻辑的基础之上,我们不能建立一个无所不包而完美的数学体系
。用图灵的话来说,一个可以解决停机问题的通用算法是不存在的。这个问题可以这样
来看,我们要让计算机解决哥德巴赫猜想(任一大於2的偶數,都可表示成兩個質數之
和),写了一个程序,从小到大尝试将这样的偶数分成两个素数的和。如果它遇到一个
不能被分解为两个素数之和的 偶数,它就停机并输出这两个偶数;否则,它就一直运
行下去。这样一来,问题就可以变成判断计算机能不能停机,知道计算机会不会停机就
是解决这个猜想。很多数学猜想实际上都可以转化成停机问题,所以说,如果有一个通
用办法,我们就可以证明很多数学猜想。
但是,图灵告诉我们,没有通用算法,只能有针对各个不同的问题的办法,当然,如果
我们找到了一个办法来判断哥德巴赫猜想的停机问题,就是解决了这个猜想。由于计算
机是一个逻辑运算的机器,这样我们就能理解哥德尔的说法,不是说哥德巴赫猜想不能
用逻辑证明(所谓证明就是逻辑),而只是说我们不能建立一个无所不包而完备的数学
体系。那么当然,在逻辑的基础之上,我们也不能建立一个理想的语言体系来说出所有
的东西,因为数学可以看成是一种语言,而且是比日常语言要简单得多。
进一步来说,对于计算机,娼妓和淑女的区别仅仅是两个字的代码不同,不可能有自己
的好恶感。从这个角度,我们也容易理解伦理学,美学都是与逻辑无关的东西,因此达
不到一致,就根本不是哲学所应该讨论的问题。就像罗素所说,所谓好坏与美丑一样,
都是各人自己的喜爱,就像萝卜白菜,
逻辑是一个有限的东西,所以计算机不可能什么都能做;同样,逻辑的有限也就造成了
语言的有限,用语言表达的所谓绝对真理一定有逻辑上的毛病。这种真理我们无法断定
存不存在,但就是有,也是不能用语言说出来的。因此,人的所知非常有限,我们只能
依靠逻辑,而逻辑有限。
我们也许还能这样说,如果我们能构造一台完美的计算机,能够解决一切数学问题,那
么当然这台计算机可以是一个绝对的参照,其它计算机都要以它来确定对错。但是,哥
德尔告诉我们在逻辑上这是不可能的;同理,也就不可能有一个人能做到这一点,没有
人能知道什么绝对真理,而让我们可以无条件的追随。那么当然,怀疑和批判就是我们
永远必须的。
当然,如果是神那就是另一个故事了,因为神是超人的,宗教与逻辑无关。有人有另一
种说法,神其实是靠人来解释的,也可以说是人造的。
所以说,计算机不但不可能是莎士比亚,也不可能写出《红楼梦》,而且,甚至有些数
学理论都不是用计算机能得到的,得依靠人的直觉,人的创造能力不能是逻辑的,爱因
斯坦那种天才人物永远是我们需要的。

哥德尔是一个奇人,极为低调,家人从别人那里才知道他在数学界的地位。很多人认为
他是上个世纪最伟大的数学家,被誉为数学上的爱因斯坦。与他同时的另一个大天才诺
依曼曾经在那个问题上作过不小的努力,但却没有成功。
“在普林斯頓時,哥德爾和愛因斯坦成了很好的朋友。後人常將他們比較。哥德爾和愛
因斯坦都在自己的範疇有極為重大的貢獻,很聰明,有好奇心,直率。但愛因斯坦性格
開朗外向,這點和哥德爾大相径庭。愛因斯坦的死對哥德爾的情緒有很大打擊。”
下面转录几段哥德尔的轶事(以下三段不是来自《维基百科》):“哥德尔曾透露他和
爱因斯坦的友谊是基于他们之间观点的不同而不是一致。哥德尔晚年在广义相对论里取
得重要成果,并于1951年被授予爱因斯坦奖。爱因斯坦晚年说:“我自己的工作没啥意
思,我来上班就是为了能有同哥德尔一起散步回家的荣幸。”我总有些好奇,这二个天
才在一起会谈些什么?我们能不能理解?
不过“罗素在普林斯顿访问时,每周都去爱因斯坦家,同爱因斯坦,哥德尔,泡利讨论
。他流露出失望:“他们仨都是流亡的犹太人,也都见多识广,但对形而上学都有德国
倾向。哥德尔根本就是个柏拉图主义者。”其实哥德尔不是犹太人。”哥德尔相信有神
论,而罗素一直对基督教持批评态度,重要原因就是柏拉图的哲学是基督教哲学(经院
哲学)直接来源,而批判柏拉图则被罗素视为自己的终身任务。
“数 学家、经济学家摩根斯顿和爱因斯坦同是哥德尔入美国籍的证人(那时入籍要证
人)。去移民局的路上,哥德尔号称可以证明美国宪法逻辑上会导致独裁。爱因斯坦
和摩根斯顿都建议哥德尔不要在移民官面前提这事,但哥德尔还是提了。爱因斯坦吸引
了移民官注意力,哥德尔顺利变成公民。”这么伟大的一个逻辑学家有这种看法,恐怕
是不错的。
“他自幼多病,而且從小就患了强迫症(疑病症)。他還患過抑鬱症。後來他在普林斯
頓的醫院絕食而死,因為他認為那些食物有毒。”“哥德爾的妻子Adele Nimbursky 比
哥德爾大六歲。哥德爾21歲兩人認識時,Adele 已婚且在夜總會 Der Nachtfalter 工
作。他們的婚姻遭到哥德爾家人反對,但有情人終成眷屬,在1938年9月20日結婚。他
們沒有小孩。”天才看来和我们这些普通人相距甚远。

我去过普林斯顿高等研究院,那是这二个天才最后工作的地方。那是一个初春,阳光灿
烂,但树荫处仍然可见积雪,春风依旧带着阵阵寒意。就像那些美国漂亮的校园,那里
开阔而人迹稀少,不由有了一些感叹,这二人的工作完全改变了世界,改变了每一个人
生活方式,但是,这里却如此寂寥!
不过这倒是与他们秉性相符,淡漠甚至有些厌恶名利,安安静静做自己喜欢的事情最好
。不过我毫无疑问地相信,只要这个世界上还存在科学和数学,他们就绝不会被人遗忘!

Standard
Uncategorized

Getting Out of Binding Situations in JavaScript

 

Getting Out of Binding Situations in JavaScript

 

Most developers don’t know about—or don’t care enough about—binding in JavaScript. Yet this single issue is responsible for a sizeable portion of the questions on most JavaScript-related support channels, and thousands—if not millions—of hairs being tortured away from developer heads every single day. Yet with a little attention to this oft-overlooked subject, you can avoid wasting your time, energy, and patience and move on to more powerful, efficient scripting.

Why should we care about binding?

Almost no major object-oriented programming (OOP) languages force you to considerbinding. That is, they don’t require you to explicitly qualify access to the current object’s members (methods and properties) with a reference such as this or self. If you’re calling a method on no particular object, you’re usually calling it on the current object. The same goes when you’re passing a method around for later invocation: it will retain its current object. In short, for most OOP languages, binding is implicit. This is true in Java, C#, Ruby, Delphi, and C++, to name but a few.

PHP and JavaScript do require you to explicitly state which object you’re accessing, even if it’s the current one. (And that is about as far as I’m willing to put PHP and JavaScript in the same basket.)

Of course, neither PHP nor JavaScript are actually object-oriented in the traditional sense. In the case of PHP, object support was added, rather slapdash, as an afterthought; even in PHP5, functions are not first-order values, and many OOPfeatures are lackluster.  JavaScript is very dynamic and relies on “prototypal inheritance,” which is a significantly different paradigm than class-based inheritance. Such distinctions do not immediately relate to binding issues, but demonstrate that traditional object-related syntaxes and behaviors were of little importance to the designers of JavaScript.

In JavaScript, binding is always explicit, and can easily be lost, so a method using thiswill not refer to the proper object in all situations, unless you force it to. Overall, binding in JavaScript is not a difficult concept, but it is far too often ignored or glossed over by JavaScripters, which leads to confusion.

Let’s step in it

Consider the following, innocuous-looking examples, and how their actual behavior can seem unpredictable.

var john = {
  name: 'John',
  greet: function(person) {
    alert("Hi " + person + ", my name is " + name);
  }
};john.greet("Mark");
// => "Hi Mark, my name is " 

Okay, that’s weird. Where did the name go?  Well, we were guilty of a binding assumption here: our method just refers to name, which JavaScript will look for in the several valid levels of variables, ending up with the properties of the window object. Of course our window does have a name property, but it’s empty by default, so no name shows up.

Let’s try it out:

name = 'Ray'; // Or explictly: window.name = 'Ray';
var john = {
  name: 'John',
  greet: function(person) {
    alert("Hi " + person + ", my name is " + name);
  }
};john.greet("Mark");
// => "Hi Mark, my name is Ray" 

Well, that’s just dandy, but useless. What we want is our object’s name property, not the one in window!  Here is where explicit binding is important:

var john = {
  name: 'John',
  greet: function(person) {
    alert("Hi " + person + ", my name is " + this.name);
  }
};john.greet("Mark");
// => "Hi Mark, my name is John" 

Notice how we prefix our reference to name with the keyword this: that’s explicit binding. And indeed it works!  Or does it? (Line wraps marked » —Ed.)

var john = {
  name: 'John',
  greet: function(person) {
    alert("Hi " + person + ", my name is " + this.name);
  }
};var fx = john.greet;
fx("Mark");
// => "Hi Mark, my name is " (or "Hi Mark, my name »
is Ray" depending on where you're trying it) 

Perhaps you’re not familiar with languages that treat functions as first-order values, in which case the line var fx = john.greet; may seem weird. This does not call thegreet method, but creates a reference to it—an alias of sorts, if you will.  Hence, callingfx ends up calling the greet method. However, we’re apparently in some trouble all of a sudden: we’re explicitly using the this keyword, yet it does not use John. What gives?

This is the single most important issue with JavaScript binding—something I’ll refer to as “binding loss.”  It happens whenever you’re accessing a method through a reference instead of directly through its owner object. The method loses its implicit binding, andthis stops referencing its owner object and goes back to its default value, which in this case is window (so if window had a name property by then, it would be used).

RECOGNIZING BINDING-SENSITIVE CODE PATTERNS

Binding-sensitive code patterns involve passing method references, which usually happens through two possible means: either you’re assigning a method as a value, or you’re passing a method as an argument (which is essentially the same thing, when you think about it).

Consider the following simple class definition (Line wraps marked » —Ed.):

function Person(first, last, age) {
  this.first = first;
  this.last = last;
  this.age = age;
}
Person.prototype = {
  getFullName: function() {
    alert(this.first + ' ' + this.last);
  },
  greet: function(other) {
    alert("Hi " + other.first + ", I'm " + »
    this.first + ".");
  }
};

Let’s try it out (Line wraps marked » —Ed.):

var elodie = new Person('Elodie', 'Jaubert', 27);
var christophe = new Person('Christophe', »
'Porteneuve', 30);
christophe.greet(elodie);
// => "Hi Elodie, I'm Christophe." 

Looking good so far.  Let’s push ahead:

function times(n, fx, arg) {
  for (var index = 0; index < n; ++index) {
    fx(arg);
  }
}times(3, christophe.greet, elodie);
// => Three times "Hi Elodie, I'm undefined." 
times(1, elodie.getFullName);
// => "undefined undefined"

Whoa—we’re in trouble!  What’s with the undefined? We lost our binding when we passed greet and getFullName as arguments, so their this reference points to thewindow object, which does not have the first and last properties.  Boom.

When you do all your JavaScript heavy lifting by hand, as we just did, you’re usually more aware of such issues. But when you rely on a framework to handle the basics, binding can elude you, leaving you writing simple code that just borks. Consider the following Prototype-based snippet:

this.items.each(function(item) {
  // Process item
  this.markItemAsProcessed(item);
});

This code will trigger an error stating that the markItemAsProcessed method is undefined.  Why is that?  Because you just passed each a reference to an anonymous function, so this in there refers to window, not to what it was outside each. This is avery common mistake, and makes up a fair share of the questions on the framework mailing lists.

Binding explicitly

So how do we fix it?  We bind explicitly—that is, we explicitly state to what this will point to within the method when it gets called.  And how do we do that?  JavaScript provides us with two options: apply and call.

APPLY WITHIN

Every JavaScript function is equipped with an apply method that allows you to call that function with specific binding (a specific this, if you will).  It takes two arguments: the binding object, and an array of the arguments to be passed to the function. Here’s an example based on our previous code:

var fx = christophe.greet;
fx.apply(christophe, [elodie]);
// => "Hi Elodie, I'm Christophe." 

The nice thing with an array is, you don’t need to know in advance which arguments the function you’ll call apply on will take. You can write code independent of the actualargument list—just construct the array any way you want, and pass it on.  You can also take an existing array of arguments and tweak it to your heart’s content before passing it along.

CALL NOW

When you do know exactly which arguments you want to pass, call may feel nicer, as it takes the arguments themselves, not an array of them:

var fx = christophe.greet;
fx.call(christophe, elodie);
// => "Hi Elodie, I'm Christophe." 

However, with call you lose the flexibility of an array. It all depends on your particular situation: aside from this difference, apply and call have identical semantics and behavior.

Note, by the way, that the method does not actually need to belong to the object you’re binding it to: as long as it uses this in ways that are compatible with its binding (read: with members that exist in its bound object), we’re in the clear. Such flexibility is possible because JavaScript is a dynamic language that resolves member access at runtime—when the access happens—a feature sometimes referred to as “late binding.” You’ll also find late binding in just about every scripting language (e.g., Perl, Ruby, Python, PHP) and, incidentally, OLE Automation.

LOSING THE SHACKLES

It’s nice to have a way to specify binding, but the problem is, you can only specify it at invocation time.  You can’t, say, specify it in advance and then let some other code invoke your properly bound method when it sees fit.  This is a major problem, because when we pass method references around, we’re doing just that: letting other code choose when to invoke methods.

So what we want is a way to persistently bind a method, so that we get a bound method reference, so to speak. The only way to achieve this requires us to wrap our original method in another one, that will perform the apply call.  Here’s a stab at it:

function createBoundedWrapper(object, method) {
  return function() {
    return method.apply(object, arguments);
  };
}

If you’re not too keen on JavaScript, the code above may confuse you a bit. The idea here is that calling createBoundedWrapper with a given object and method (which, presumably, belongs to said object) will produce a brand new function (the anonymous one we’re returning).

That function, when called, will take our original method and invoke apply on it, passing:

  1. the original object’s binding (the variable named object), and
  2. whatever arguments were provided at call time, as an array.

(Every function has an automatic arguments variable that behaves as an array of all the arguments that were passed to it.)

Let’s try it out (Line wraps marked » —Ed.):

var chrisGreet = createBoundedWrapper(christophe, »
christophe.greet);
chrisGreet(elodie);
// "Hi Elodie, I'm Christophe." 

Ah-ha!  It works!  We created a bound method reference based on christophe and itsgreet method.

JavaScript frameworks do it

Our createBoundedWrapper function is neat, but may prove a bit unwieldy. If you’re smart about your JavaScript work, you’ll probably rely on a framework to smooth out browser incompatibilities, ease DOM access, and enhance JavaScript. So let’s have a look at how a few popular JavaScript frameworks deal with method binding.

PROTOTYPE

Prototype has long equipped functions with a bind method that lets you do just that:

var chrisGreet = christophe.greet.bind(christophe);
chrisGreet(elodie);

Far too few people know that bind also allows you to do “partial application”—that is, pre-filling one or more arguments. For instance, let’s say you have a method that toggles the active status of a feature:

var coolBehavior = {
  // ...
  toggle: function(enabled) {
    this.enabled = enabled;
    // ...
  },
  // ...
};

You can easily define two shortcuts—enable and disable—in the following way (Line wraps marked » —Ed.):

coolBehavior.enable = coolBehavior.toggle.bind »
(coolBehavior, true);
coolBehavior.disable = coolBehavior.toggle.bind »
(coolBehavior, false);// And then:
coolBehavior.enable();

A note on proper usage: sometimes, bind was used for pre-filling only, without interest in the binding.  Something like the following may be seen in code:

function times (count, fx) {
  for (var index = 0; index < count; ++index) {
    fx();
  }
}
// ...
var threeTimes = times.bind(null, 3);
// ...
threeTimes(someFunction);

So as a side note, with Prototype 1.6, if you’re only interested in pre-filling, prefercurry—it preserves the current binding and focuses on argument pre-filling:

var threeTimes = times.curry(3);

Ext JS

The Ext JS library tailors binding through a method added to functions, calledcreateDelegate. The syntax goes like this (Line wraps marked » —Ed.):

method.createDelegate(scope[, argArray] »
[, appendArgs = false])

First, note that the extra arguments you may specify are provided as an array, instead of inline: myMethod.createDelegate(scope, [arg1, arg2]), notmyMethod.createDelegate(scope, arg1, arg2).

Another important nuance is that these arguments will replace whatever arguments you pass at call time, instead of resulting in partial application. If you want the latter, you need to pass true (which will append the argument array, when Prototype would prepend them instead) or an insert position as a third argument (typically, using zero will prepend).  Here’s an example lifted from the API documentation (Line wraps marked » —Ed.):

var fn = scope.func1.createDelegate(scope, »
[arg1, arg2], true);
fn(a, b, c); // => scope.func1(a, b, c, arg1, arg2);var fn = scope.func1.createDelegate(scope, »
[arg1, arg2]);
fn(a, b, c); // => scope.func1(arg1, arg2);var fn = scope.func1.createDelegate(scope, »
[arg1, arg2], 1);
fn(a, b, c); // => scope.func1(a, arg1, arg2, b, c);

DOJO

The Dojo toolkit also caters to method binding with the humorously named hitchfunction.  The syntax is:

dojo.hitch(scope, methodOrMethodName[, arg…])

Interestingly, the method can be passed either directly, or using its name. Extra arguments, if any, are passed before actual, call-time arguments. Here are a few examples:

var fn = dojo.hitch(scope, func1)
fn(a, b, c); // => scope.func1(a, b, c);var fn = dojo.hitch(scope, func1, arg1, arg2)
fn(a, b, c); // => scope.func1(arg1, arg2, a, b, c);

BASE2

Dean Edwards’ superb Base2 library acts as a least common denominator of sorts to all JavaScript libraries by ironing out all the annoying differences in JavaScript implementations. It acknowledges a binding facility is needed and provides a simplebind function:

base2.bind(method, scope[, arg]);

Note the scope object comes second, not first. Aside from that, the semantics are strictly equivalent to Prototype’s bind or Dojo’s hitch:

var fn = base2.bind(func1, scope)
fn(a, b, c); // => scope.func1(a, b, c);var fn = base2.bind(func1, scope, arg1, arg2)
fn(a, b, c); // => scope.func1(arg1, arg2, a, b, c);

JQUERY

jQuery does not provide such a binding facility. The library’s philosophy favors closures over binding and forces users to jump through hoops (that is, manually combine lexical closures and apply or call, much as other libraries do internally) when they actually need to pass along a piece of code referring to “instance members.”

Should you even bind?

Now that we’ve been through the details of binding, it’s only fair to stress that sometimes, binding is overkill.  Specifically, there’s a code pattern in which binding can be replaced, with significant performance profit, by using the lexical closure. (If you’re not clear on a what a closure is, don’t panic.)

Here’s the pattern: some code within a method relies on an anonymous function passed by reference to work. That anonymous function needs to access the surrounding method’s this keyword. For instance, assuming for a minute we have the eachiterator within arrays, consider the following code again:

  // ...
  processItems: function() {
    this.items.each(function(item) {
      // Process item…
      this.markItemAsProcessed(item);
    });
  },
  // ...

The issue here is that the anonymous function holding the actual processing code is passed as an argument to each, and therefore loses the current binding.  When it attempts to call this.markItemAsProcessed, it crashes because window has no such method.

Many developers are quick to fix that with binding. Using Prototype, for instance, they would add the following tweak:

  // ...
  processItems: function() {
    this.items.each(function(item) {
      // Process item
      this.markItemAsProcessed(item);
    }.bind(this));
  },
  // ...

Notice the trailing call to bind. However, such code is not as good an idea as it may seem. We saw that achieving such a “bound reference” requires us to wrap the original method within an anonymous function, which means calling the bound method reference results in two method calls: our anonymous wrapper, and the original method. And if there’s one thing true of just about any language, it’s that method calls are costly.

In this situation, we have access to the original, desired this keyword in the same code location where we define and call the faulty function (the anonymous method we’re passing as an argument to each). We can simply save the proper this reference in a local variable, and use that inside our iteration function:

  // ...
  processItems: function() {
    var that = this;
    this.items.each(function(item) {
      // Process item
      that.markItemAsProcessed(item);
    });
  },
  // ...

Look, Ma!  No binding!  This code uses a language feature called “lexical closure.” In short, closures let code at point A access identifiers declared in scopes surrounding A. Here, our anonymous function has access to variables in the surrounding function—ourprocessItems method. Such a closure will be maintained by the JavaScript runtime no matter what, so there is no extra cost to using it. Even if there were, I’m fairly confident that it would be far less than the cost of an extra function call at every turn of the loop.

Be cautious about your bindings: sometimes closures provide a simpler, shorter, and better way. (Which is, I believe, precisely why jQuery decided to “force” its users to think about the best option for each situation by having them deal with binding manually.) While closures do have their own set of problems—ill-employed, they can result in memory leaks for certain browsers—the usage I recommend here is pretty safe.

Takeaway points

To recap:

  • Any member access must be qualified with the object it pertains to, even when it is this.
  • Any sort of function reference (assigning as a value, passing as an argument) loses the function’s original binding.
  • JavaScript provides two equivalent ways of explicitly specifying a function’s binding when calling it: applyand call.
  • Creating a “bound method reference” requires an anonymous wrapper function, and a calling cost. In specific situations, leveraging closures may be a better alternative.

And now, with the help of this article, you’ll have no trouble in binding situations!

Standard