ECMAScript 5.1 (或仅 ES5) 是ECMAScript(基于JavaScript的规范)标准最新修正。其中,新增了一个名叫bind
函数扩展方法(),以前有提过,点击这里查看详细。
不过,之前的介绍纯粹的翻译,含糊其辞,水土不服,这里,换身接地气的装束,让大家好好了解了解。
李元芳:jQuery? 大人,莫非就是最近江湖广为流传,从米国传过来的开发利器?
李元芳:什么?这西洋利器也有bind
方法。属下孤陋寡闻,望大人指点明津!
狄仁杰:jQuery的包装器扩展了一个bind
方法,可以用来绑定事件。
李元芳:大人果然学贯中外,居然可以知道jQuery的bind
是用来绑定事件的,属下实在佩服!!
李元芳:大人,内衣弄来了,长这样:
$("#test").bind("click", function() { console.log("内衣你妹!"); });
狄仁杰:呵呵,这就证实了jQuery的bind
是对包装器的扩展!
李元芳:纳尼!发酵了这么久,原来不是茅台是酱油!大人,那幕后主谋究竟是?
狄仁杰:元芳,你可知prototype.js
以及MooTools.js
中的bind
方法?
李元芳:大人,什么prototype.js
还有MooTools.js
?小的听糊涂了。
狄仁杰:这可不怪你,你前些日子忙着和如燕造人,江湖消息没能及时获取。
狄仁杰:大人我知道的事情可多着呢!prototype.js
和MooTools.js
都是米国过来的开发利器,不过江湖名声威望不及jQuery;但仍有不少帮派以及小村寨使用之。
李元芳:原来是这样,怪不得大人让我去取豆瓣的内衣而不是点评的!大人果然深谋远虑,那这两个利器的bind
方法是?
狄仁杰:元芳,你这个问题问得好!你可以看这一集的标题,就会知道答案了!
李元芳:原来如此,属下一下子明白了——MooTools.js
的bind
方法是对函数的扩展!大人这么远都能明察秋毫,真乃神人也!!
狄仁杰:元芳,下面这段代码你怎么看?
var button = document.getElementById("button"); button.onclick = function() { alert(this.id); // 弹出button };
李元芳:大人,虽然我不懂洋文,但我可以确定这段代码一定藏有天大的玄机。
李元芳:大人,暗藏机关您都可以一眼看出来啊!!属下终于明白周星驰常说的”我对你的敬仰犹如滔滔江水连绵不绝,又如黄河泛滥一发不可收拾…”的含义了……
狄仁杰:元芳,下面这段代码你又怎么看?
var button = document.getElementById("button"), text = document.getElementById("text"); button.onclick = function() { alert(this.id); // 弹出text }.bind(text);
李元芳:莫非这就是bind的作用——改变了函数内部的上下文this
?!
旁白:元芳此时定睛看了看短词少句的剧本,脸色立马变大便,眼睛直接变成了火影中的白眼……
李元芳:——擦,吃翔了我!!sorry啊,大人,我台词看错行了!!求鞭笞!
狄仁杰:(稳定了情绪,长舒了一口气~~)我们这是荒诞搞笑剧,不是SM剧,鞭笞什么的就算了!不过下面我要多讲几句,寻求心理平衡!
狄仁杰:函数扩展bind
使用如下:
function() {}.bind(thisArg [, arg1 [, arg2, …]]);
翻译成唐文就是:
函数.bind(this上下文参数, 普通参数1, 普通参数2, ...);
根据我的实践与调查,bind
方法尤其在对象字面量编程风格下尤为受用。
var OOO = { color: "#cd0000", element: $("#text"), events: function() { $("input[type='button']").addEventListener("click", function(e) { this.element.style.color = this.color; }.bind(this)); return this; }, init: function() { this.events(); } };
李元芳:《葵花宝典》!是不是那个几百年之后,宫中那个名叫”无二弟郎”创建的一门神功?
李元芳:什么?武功也会搞歧视……大人,那这门武功看哪些人不顺眼呢?
李元芳:哦?居然还有这等玄机!莫非bind
方法我又不能使用?
狄仁杰:那倒不是。N多年前,有一族姓氏为ie的外人迁至我大唐,其目前留在世上的第6~8
代后人是不能使用bind方法的,逐渐长大的第9代后人,以及还在襁褓中的第10代后人倒是可以使用!
李元芳:大人如此见多识广,真可谓当代奇人啊!那这IE6~8终日不得惶恐,岂不是很悲剧?
狄仁杰:就跟《葵花宝典》清了裤裆依然可以练一样,IE6~8也是有办法不被歧视,避免悲剧的!
导演:咔!!本集拍完了,广告时间,大伙休息下,马上进入下集拍摄!
//zxx: 下面为广告~~注意不要勿点~~嘻嘻~~
狄仁杰:通过对Function
的prototype
原型进行扩展,可以为IE6~8自定义bind
方法。元芳,你可知如何自定义?
李元芳:大人,您是知道的,我不能抢你的风头。因此,属下不知,请大人道明真相!
曾泰:恩师,下面的密函文字都是English, 我不认识字啊!
if (!function() {}.bind) { Function.prototype.bind = function(context) { var self = this , args = Array.prototype.slice.call(arguments); return function() { return self.apply(context, args.slice(1)); } }; }
狄仁杰:曾泰,你的脑袋还是一如既往的秀逗,既然是密文,你就用密语念就行了!
曾泰:恩师当真高明!&……#&……¥&*@¥%#…%#%¥&*……
狄仁杰:元芳,曾泰,你们都过来,顺便把你们的鼠标都移过来,狠狠地点击这里:为函数自定义bind方法demo
狄仁杰:呵呵,说明你可以使用bind方法!曾泰,我没记错的话,你就是ie家族第八代后人,后因坑爹致死跟妈姓才改姓曾,你也来试试机关!
曾泰:恩师,我也变红了!
我勒个去,我还有如此悲惨的剧情设定啊!好吧,人在江湖漂,哪有不挨刀!被ie,被克父,被红了都认了!
狄仁杰:红了好啊,红了好啊!说明密函中的自定义方法是有效的!
机关对应的密文更能说明这一切:
var eleBtn = document.getElementById("button") , eleText = document.getElementById("text"); eleBtn.onclick = function(color) { color = color || "#003399"; this.style.color = color; }.bind(eleText, "#cd0000");
李元芳:不过大人,我还有不解,密文中Array.prototype.slice.call(arguments)
是什么意思?
导演:咔!!本集over. 那个,我老婆催我回去早点休息了。因此,下一集我一个人来演就可以了。大家都散了吧,各回各家,各找各妈!
李元芳/曾泰(异口同声):导演,我们现在红得像个卫生巾一样,回不了家啊,先帮我们还原吧!
导演:回不了家,那正好!路口红灯正好坏了,你们俩过去,不要浪费了资源!
查看jQuery的源代码,会看到类似:
slice = Array.prototype.slice,
或
array = Array.prototype.slice.call( array, 0 );
的代码。
干嘛用的呢?
作用就是:将类似数组的对象转换为真实的数组。
真实数组具有slice
方法,可以对数组进行浅复制(不影响原数组),返回的依然是数组。
类似数组虽然有length属性,可以使用for
循环遍历,却不能直接使用slice方法,会报错!但是通过Array.prototype.slice.call
则不会报错,本身(类似数组)被从头到尾slice复制了一遍——变成了真实数组!
上一集demo中函数内部的arguments
是应该都熟知的类似数组,于是:
Array.prototype.slice.call(arguments)
所返回的就是完整参数的真实数组了!下面的code也就容易理解了。
至于为什么”类似数组不能直接slice
, 而借助Array.prototype
可以slice
我也不清楚其中深层次的原因,还希望有过相关研究的大人指点迷津!