关于Function.prototype.bind

bind()方法会建立一个新函数,称为绑定函数。当调用这个绑定函数时,绑定函数会以建立它时传入bind()方法的第一个参数做为 this,传入 bind() 方法的第二个以及之后的参数加上绑定函数运行时自己的参数按照顺序做为原函数的参数来调用原函数。javascript

实际使用中咱们常常会碰到这样的问题:java

 

js 代码:浏览器

  1. function Person(name){
  2. this.nickname = name;
  3. this.distractedGreeting = function() {
  4.  
  5. setTimeout(function(){
  6. console.log("Hello, my name is " + this.nickname);
  7. }, 500);
  8. }
  9. }
  10.  
  11. var alice = new Person('Alice');
  12. alice.distractedGreeting();
  13. //Hello, my name is undefined

这个时候输出的this.nickname是undefined,缘由是this指向是在运行函数时肯定的,而不是定义函数时候肯定的,再由于setTimeout在全局环境下执行,因此this指向setTimeout的上下文:window缓存

之前解决这个问题的办法一般是缓存this,例如:app

 

js 代码:函数

  1. function Person(name){
  2. this.nickname = name;
  3. this.distractedGreeting = function() {
  4. var self = this; // <-- 注意这一行!
  5. setTimeout(function(){
  6. console.log("Hello, my name is " + self.nickname); // <-- 还有这一行!
  7. }, 500);
  8. }
  9. }
  10.  
  11. var alice = new Person('Alice');
  12. alice.distractedGreeting();
  13. // after 500ms logs "Hello, my name is Alice"

这样就解决了这个问题,很是方便,由于它使得setTimeout函数中能够访问Person的上下文。可是看起来稍微一种蛋蛋的忧伤。this

可是如今有一个更好的办法!您可使用bind。上面的例子中被更新为:spa

 

js 代码:prototype

  1. function Person(name){
  2. this.nickname = name;
  3. this.distractedGreeting = function() {
  4. setTimeout(function(){
  5. console.log("Hello, my name is " + this.nickname);
  6. }.bind(this), 500); // <-- this line!
  7. }
  8. }
  9.  
  10. var alice = new Person('Alice');
  11. alice.distractedGreeting();
  12. // after 500ms logs "Hello, my name is Alice"

bind() 最简单的用法是建立一个函数,使这个函数不论怎么调用都有一样的 this 值。JavaScript新手常常犯的一个错误是将一个方法从对象中拿出来,而后再调用,但愿方法中的 this 是原来的对象。(好比在回调中传入这个方法。)若是不作特殊处理的话,通常会丢失原来的对象。从原来的函数和原来的对象建立一个绑定函数,则能很漂亮地解决这个问题:code

 

js 代码:

  1. this.x = 9;
  2. var module = {
  3. x: 81,
  4. getX: function() { return this.x; }
  5. };
  6.  
  7. module.getX(); // 81
  8.  
  9. var getX = module.getX;
  10. getX(); // 9, 由于在这个例子中,"this"指向全局对象
  11.  
  12. // 建立一个'this'绑定到module的函数
  13. var boundGetX = getX.bind(module);
  14. boundGetX(); // 81

浏览器支持:

Browser Version support
Chrome 7
Firefox (Gecko) 4.0 (2)
Internet Explorer 9
Opera 11.60
Safari 5.1.4

很不幸,Function.prototype.bind 在IE8及如下的版本中不被支持,因此若是你没有一个备用方案的话,可能在运行时会出现问题。bind 函数在 ECMA-262 第五版才被加入;它可能没法在全部浏览器上运行。你能够部份地在脚本开头加入如下代码,就能使它运做,让不支持的浏览器也能使用 bind() 功能。

幸运的是,MDN为没有自身实现 .bind() 方法的浏览器提供了一个绝对可靠的替代方案:

 

js 代码:

  1. if (!Function.prototype.bind) {
  2. Function.prototype.bind = function (oThis) {
  3. if (typeof this !== "function") {
  4. // closest thing possible to the ECMAScript 5 internal IsCallable function
  5. throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
  6. }
  7.  
  8. var aArgs = Array.prototype.slice.call(arguments, 1),
  9. fToBind = this,
  10. fNOP = function () {},
  11. fBound = function () {
  12. return fToBind.apply(this instanceof fNOP && oThis
  13. ? this
  14. : oThis || window,
  15. aArgs.concat(Array.prototype.slice.call(arguments)));
  16. };
  17.  
  18. fNOP.prototype = this.prototype;
  19. fBound.prototype = new fNOP();
  20.  
  21. return fBound;
  22. };
  23. }

参考阅读:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

http://www.smashingmagazine.com/2014/01/23/understanding-javascript-function-prototype-bind/

http://krasimirtsonev.com/blog/article/JavaScript-bind-function-setting-a-scope

语法

fun.bind(thisArg[, arg1[, arg2[, …]]])

参数

thisArg
当绑定函数被调用时,该参数会做为原函数运行时的 this 指向.当使用new 操做符调用绑定函数时,该参数无效.
arg1, arg2, …
当绑定函数被调用时,这些参数加上绑定函数自己的参数会按照顺序做为原函数运行时的参数.

描述

bind() 函数会建立一个新的函数(一个绑定的函数)有一样的函数体(在 ECMAScript 5 规范内置 Call 属性),当该函数(绑定函数的原函数)被调用时 this 值绑定到 bind() 的第一个参数,该参数不能被重写。绑定函数被调用时,bind() 也接受预设的参数提供给原函数。一个绑定函数也能使用 new 操做符 建立对象:这种行为就像把原函数当成构造器。提供的 this 值被忽略,同时调用时的参数被提供给模拟函数。

相关文章
相关标签/搜索