这篇文章发布于 2012年10月12日,星期五,17:27,归类于 JS API。 阅读 142966 次, 今日 3 次 40 条评论
by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=2689
ECMAScript 5.1 (或仅 ES5) 是ECMAScript(基于JavaScript的规范)标准最新修正。其中,新增了一个名叫bind
函数扩展方法(),以前有提过,点击这里查看详细。
不过,之前的介绍纯粹的翻译,含糊其辞,水土不服,这里,换身接地气的装束,让大家好好了解了解。
一、对函数扩展的bind方法
狄仁杰:元芳,你对bind
怎么看?
李元芳:大人,这一定是个很有用的方法!
狄仁杰:我可以断定,bind
是一个方法!
李元芳:大人未经实践就知道bind
是一个方法,真乃神人也!
狄仁杰:而且是个扩展方法!
李元芳:什么?扩展方法?大人,属下愚钝,听不明白!
狄仁杰:元芳,你可认识jQuery?
李元芳:jQuery? 大人,莫非就是最近江湖广为流传,从米国传过来的开发利器?
狄仁杰:正是!你可知其中也有bind
方法?
李元芳:什么?这西洋利器也有bind
方法。属下孤陋寡闻,望大人指点明津!
狄仁杰:jQuery的包装器扩展了一个bind
方法,可以用来绑定事件。
李元芳:大人果然学贯中外,居然可以知道jQuery的bind
是用来绑定事件的,属下实在佩服!!
狄仁杰:元芳,你速去豆瓣弄件jQuery的浅色内衣。
李元芳:大人,内衣弄来了,长这样:
$("#test").bind("click", function() { console.log("内衣你妹!"); });
狄仁杰:呵呵,这就证实了jQuery的bind
是对包装器的扩展!
李元芳:大人,果然事件结果都被你一一说中!
狄仁杰:不过jQuery的bind
并不是幕后主谋!
李元芳:纳尼!发酵了这么久,原来不是茅台是酱油!大人,那幕后主谋究竟是?
狄仁杰:元芳,你可知prototype.js
以及MooTools.js
中的bind
方法?
李元芳:大人,什么prototype.js
还有MooTools.js
?小的听糊涂了。
狄仁杰:这可不怪你,你前些日子忙着和如燕造人,江湖消息没能及时获取。
李元芳:大人,造人的事情你都知道啊!
狄仁杰:大人我知道的事情可多着呢!prototype.js
和MooTools.js
都是米国过来的开发利器,不过江湖名声威望不及jQuery;但仍有不少帮派以及小村寨使用之。
李元芳:原来是这样,怪不得大人让我去取豆瓣的内衣而不是点评的!大人果然深谋远虑,那这两个利器的bind
方法是?
狄仁杰:元芳,你这个问题问得好!你可以看这一集的标题,就会知道答案了!
李元芳:大人,导演插了太多图片,距离太远看不到了!
狄仁杰:恩?还有这种事!来人,给元芳拿个望远镜过来!
路人甲递过一个御用望远镜……
李元芳:原来如此,属下一下子明白了——MooTools.js
的bind
方法是对函数的扩展!大人这么远都能明察秋毫,真乃神人也!!
狄仁杰:元芳,你可知这里的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);
李元芳:根据大人之前的推断,点击某个机关后会弹出一个暗器!
狄仁杰:……
李元芳:而且这个名字的暗器叫做”text”.
狄仁杰:……
李元芳:但是,奇怪啊,为什么弹出暗器是”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
方法跟《葵花宝典》一样,不是谁都可以用的?
李元芳:哦?居然还有这等玄机!莫非bind
方法我又不能使用?
狄仁杰:那倒不是。N多年前,有一族姓氏为ie的外人迁至我大唐,其目前留在世上的第6~8
代后人是不能使用bind方法的,逐渐长大的第9代后人,以及还在襁褓中的第10代后人倒是可以使用!
李元芳:大人如此见多识广,真可谓当代奇人啊!那这IE6~8终日不得惶恐,岂不是很悲剧?
狄仁杰:就跟《葵花宝典》清了裤裆依然可以练一样,IE6~8也是有办法不被歧视,避免悲剧的!
李元芳:大人,那这个方法是?
狄仁杰:这个方法就是……
导演:咔!!本集拍完了,广告时间,大伙休息下,马上进入下集拍摄!
//zxx: 下面为广告~~注意不要勿点~~嘻嘻~~
二、为IE6~8自定义bind方法
李元芳:大人,您先~~
狄仁杰:通过对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. 那个,我老婆催我回去早点休息了。因此,下一集我一个人来演就可以了。大家都散了吧,各回各家,各找各妈!
李元芳/曾泰(异口同声):导演,我们现在红得像个卫生巾一样,回不了家啊,先帮我们还原吧!
导演:回不了家,那正好!路口红灯正好坏了,你们俩过去,不要浪费了资源!
李元芳/曾泰:……
三、小拓展 – Array.prototype.slice.call
查看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
我也不清楚其中深层次的原因,还希望有过相关研究的大人指点迷津!
本文为原创文章,转载请注明来自张鑫旭-鑫空间-鑫生活[http://www.zhangxinxu.com]
本文地址:http://www.zhangxinxu.com/wordpress/?p=2689
(本篇完)
- 翻译:ECMAScript 5.1简介 (0.716)
- 我对原型对象中this的一个懵懂错误认识 (0.284)
- jQuery诞生记-原理与机制 (0.284)
- 近期手机网页项目一些杂碎心得分享 (0.142)
- ES5中新增的Array方法详细说明 (0.142)
- 翻译-高质量JavaScript代码书写基本要点 (0.102)
- 漫谈js自定义事件、DOM/伪DOM自定义事件 (0.102)
- HTML静态页面原型交付工具“魔卡”简介 (0.095)
- IE6下png背景不透明问题的综合拓展 (0.007)
- jQuery-很酷的弹出层效果js插件 (0.007)
- 给IE/Edge写了个textarea resize拉伸的polyfill (RANDOM - 0.007)
document.querySelectorAll(‘img’).forEach(img => img.parentNode.removeChild(img));
你真是个逗比
真是有时间啊 弄这么多图片
张老师真乃神人也
旭哥,有个问题想请教一下,定时器里的回调函数调用bind会不会内存溢出啊?还是当bind里的apply方法执行完毕之后就会销毁这个闭包作用域啊?
如:setTimeout(arguments.callee.bind(HZEPG.Scroll), this.valueTime)
超级有意思,更好理解,非常喜欢这种风格!有意思的学技术,有自己独特的理解。不错的老师!哈哈!
密函里返回的函数的arguments 被漏掉了
希望能短 一点 幽默要有个°
对啊,,,图片稍微有点多了
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));
}
};
}
这个中,,, return self.apply(context, args.slice(1)); 里面这个1看不懂,求解释,我感觉应该不写这个值
跳过第一个,从第二个开始,第一个就是要绑定的对象context
受益匪浅呀 顺便收藏了
哈哈哈,每次看你的文档,都是又涨知识又有趣!赞。怎么会有这样的人呢
卧槽 旭哥真是太有才了!!!!
12年写的,我最近才用到。写的不错啊,旭哥,前端时间我移动端项目就用你的mobilebone.js来实现的
中国缺少如此幽默的技术文章,值得推荐!
此博主的博客内容还是有很多经典的好东西, 但是越来越没看头了, 其实内容都是不错的,就是写的太搞了,搞的有点过分,甚至看不懂
@至于为什么”类似数组不能直接slice, 而借助Array.prototype可以slice”我也不清楚其中深层次的原因,还希望有过相关研究的大人指点迷津!
而借助Array.prototype可以slice,这里有问题吧。借助也是不可以的。
我理解的是,一个对象没有slice函数属性,但还是可以被slice函数执行吧,这里只是调用了slice函数而已。至于为什么不直接Array.prototype.slice(arguments),slice函数本身是为Array设计的,内部肯定调用上下文this,而不是某个参数名。所以,我想[].slice(arguments)也是一样的结果吧。
@wubai 写js多了吧。那么麻烦 直接找到图片。样式display:none 看的多清爽~~~~
看的我好累!
用火狐看,在firebug控制台输入如下代码,运行即可缩小那些图片:
var imgs = document.getElementById(‘post-2689’).getElementsByTagName(‘img’);
var imgsLen = imgs.length;
for(var i=0; i<imgsLen; i++){
imgs[i].style.height='50px';
imgs[i].style.width='auto';
}
直接height为0
哈哈,笑抽了,你太有才了。
写得很欢乐的文章!期待能从博主的博文中学到更多的东西!
我一直关注你写的文章,其中这一片我觉得写的太搞笑了,实在没办法不看,
还有一篇也极为搞笑,好吧,CSS3 3D transform变换,不过如此!
博主,我十分想知道什么样的女人适合你
牛了吧唧的~!
好创意啊!不过把配图稍微改小点可能更好。
博主好幽默
这看得太累了,以前的文章很好,最近都弄这个…
看着真累,配图又大,滚动鼠标都滚累了。
不过表现形式感觉还是有点意思,就是内容太累了。
呃,这章写的我蛋疼
这个bind的写法不够完善,没达到扩展参数的效果
var obj = { value: []};
var a = function(){
for( var i = 0; i < arguments.length; i++ ){
this.value.push(arguments[i]);
}
return this.value;
}.bind( obj,4,5,6 );
console.log(a(1,2,3 ));
这里可以看出,
看到更多的是这类
Function.prototype.bind =
function (context) {
var method = this,
slice = Array.prototype.slice,
args = slice.call(arguments, 1),
innerArgs,finalArgs;
return function () {
innerArgs = slice.call(arguments);
finalArgs = args.concat(innerArgs)
return method.call(context,finalArgs);
};
};
鑫哥我 用您的 /*Function.prototype.bind = function(context) {
var self = this, args = Array.prototype.slice.call(arguments);
return (function() {
console.log(args.slice(1))
return self.apply(context, args.slice(1));
})
}*/
在ie8下测试 有问题,本来结果是 4,5,6,1,2,3 在ie8 下只有4,5,6 用楼上的这段代码是可以的
哈哈,太搞了。。。
真象只有一个
不去搞文学真实浪费了啊
这么快就回复了,这后面一定有一个天大的机密
@tcdona 还望大人指明真相!
这篇写的,,,
哈哈 太搞笑了~
@immkoala @tamamadesu 你们评论怎么可以这么迅速!!