Javascript Function.prototype.bind详细分析


Posted in Javascript onDecember 29, 2016

  Function.prototype.bind分析

bind()方法会创建一个新的函数,成为绑定函数。当调用这个绑定函数时,绑定函数会以创建它时传入的第一个参数作为this,传入bind()方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调取原函数。

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

var name = "pig";
function Person(name){
  this.name = name;
  this.getName = function(){
    setTimeout(function(){
      console.log("Hello,my name is "+this.name);
    },100);
  }
}
var weiqi = new Person("卫旗");
weiqi.getName();  
//Hello,my name is pig

       这个时候输出this.name是pig,原因是this的指向是在运行函数时确定的,而不是在定义函数时确定的,再因为setTimeout是在全局环境下只想,所以this就指向了window。

       以前解决这个问题的办法通常是缓存this,例如:

var name = "pig";
function Person(name){
  this.name = name;
  this.getName = function(){
    //在这里缓存一个this
    var self = this;
    setTimeout(function(){
      //在这里是有缓存this的self
      console.log("Hello,my name is "+self.name);
    },100);
  }
}
var weiqi = new Person("卫旗");
weiqi.getName();
//Hello,my name is 卫旗

       这样就解决了这个问题,非常方便,因为它使得setTimeout函数中可以访问Person的上下文。

       现在有一个更好的解决办法,可以使用bind()函数,上面的例子可以被更新为:

var name = "pig";
function Person(name){
  this.name = name;
  this.getName = function(){
    setTimeout(function(){
      console.log("Hello,my name is "+this.name);
    }.bind(this),100);
    //注意上面这一行,添加了bind(this)
  }
}
var weiqi = new Person("卫旗");
weiqi.getName();
//Hello,my name is 卫旗

       bind()最简单的用法是创建一个函数,使得这个函数无论怎么样调用都拥有同样的this值。JavaScript新手经常犯的一个错误就是将一个方法从一个对象中拿出来,然后再调用,希望方法中的this是原来的对象(比如在回调函数中传入这个方法)。如果不做特殊处理的话,一般会丢失原来的对象。从原来的函数和原来的对象创建一个绑定函数,则可以很漂亮的解决这个问题:

//定义全局变量x
var x = "window";
//在module内部定义x
var module = {
  x:"module",
  getX:function(){
    console.log(this.x);
  }
}
module.getX(); 
//返回module,因为在module内部调用getX()

var getX = module.getX;
getX();
//返回window,因为这个getX()是在全局作用域中调用的

//绑定getX()并将this值设为module
var boundGetX = getX.bind(module);
boundGetX();
//返回module,绑定以后this值始终为module

浏览器支持情况:

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

       很不幸,Function.prototype.bind在IE8及以下版本中不被支持,所以如果没有一个备选方案的话,可能会在运行时出现问题。bind函数在ECMA-262第五版才被加入。它可能不无法在所有浏览器上运行。你可以在脚本部分加入如下代码,让不支持的浏览器也能使用bind()功能。

if (!Function.prototype.bind) {
 Function.prototype.bind = function (oThis) {
  if (typeof this !== "function") {
   // closest thing possible to the ECMAScript 5 internal IsCallable function
   throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
  }

  var aArgs = Array.prototype.slice.call(arguments, 1), 
    fToBind = this, 
    fNOP = function () {},
    fBound = function () {
     return fToBind.apply(this instanceof fNOP && oThis
                 ? this
                 : oThis || window,
                aArgs.concat(Array.prototype.slice.call(arguments)));
    };

  fNOP.prototype = this.prototype;
  fBound.prototype = new fNOP();

  return fBound;
 };
}

语法

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

参数

       thisArg,当绑定函数被调用时,该参数会作为原函数运行时的this指向,当使用new操作符调用绑定函数时,该参数无效。

       arg1, arg2, …,当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数。

描述

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

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
使用自定义setTimeout和setInterval使之可以传递参数和对象参数
Apr 24 Javascript
JavaScript 异步调用框架 (Part 5 - 链式实现)
Aug 04 Javascript
JavaScript中的集合及效率
Jan 08 Javascript
javascript自执行函数之伪命名空间封装法
Dec 25 Javascript
用最通俗易懂的代码帮助新手理解javascript闭包 推荐
Mar 01 Javascript
DOM节点的替换或修改函数replaceChild()用法实例
Jan 12 Javascript
纯javascript实现的小游戏《Flappy Pig》实例
Jul 27 Javascript
js实现简单排列组合的方法
Jan 27 Javascript
jQuery操作动态生成的内容的方法
May 28 Javascript
利用Jquery实现几款漂亮实用的时间轴(附示例代码)
Feb 15 Javascript
angular ng-model 无法获取值的处理方法
Oct 02 Javascript
JavaScript 对引擎、运行时、调用堆栈的概述理解
Oct 22 Javascript
jQuery自定义插件详解及实例代码
Dec 29 #Javascript
canvas快速绘制圆形、三角形、矩形、多边形方法介绍
Dec 29 #Javascript
JavaScript获取短信验证码(周期性)
Dec 29 #Javascript
JavaScript实现同一个页面打开多张图片
Dec 29 #Javascript
Javascript 对cookie操作详解及实例
Dec 29 #Javascript
前端 Vue.js 和 MVVM 详细介绍
Dec 29 #Javascript
javascript显示系统当前时间代码
Dec 29 #Javascript
You might like
php数组一对一替换实现代码
2012/08/31 PHP
laravel框架实现后台登录、退出功能示例
2019/10/31 PHP
在视频前插入广告
2006/11/20 Javascript
javascript中的undefined 与 null 的区别  补充篇
2010/03/17 Javascript
jQuery Validation PlugIn的使用方法详解
2015/12/18 Javascript
详解maxlength属性在textarea里奇怪的表现
2015/12/27 Javascript
D3.js实现雷达图的方法详解
2016/09/22 Javascript
js实现刷新页面后回到记录时滚动条的位置【两种方案可选】
2016/12/12 Javascript
详解如何让InstantClick兼容MathJax、百度统计等
2017/09/12 Javascript
jQuery实现table中两列CheckBox只能选中一个的示例
2017/09/22 jQuery
vue刷新和tab切换实例
2018/02/11 Javascript
重新认识vue之事件阻止冒泡的实现
2018/08/02 Javascript
vue+axios 前端实现登录拦截的两种方式(路由拦截、http拦截)
2018/10/24 Javascript
vue-router传参用法详解
2019/01/19 Javascript
vue实现表单录入小案例
2019/09/27 Javascript
解决Vue使用bus总线时,第一次路由跳转时数据没成功传递问题
2020/07/28 Javascript
[01:15:16]DOTA2-DPC中国联赛 正赛 Elephant vs Aster BO3 第一场 1月26日
2021/03/11 DOTA
跟老齐学Python之眼花缭乱的运算符
2014/09/14 Python
Python的Bottle框架中返回静态文件和JSON对象的方法
2015/04/30 Python
python魔法方法-属性转换和类的表示详解
2016/07/22 Python
Python 两个列表的差集、并集和交集实现代码
2016/09/21 Python
python实现简易版计算器
2020/06/22 Python
python基础教程项目二之画幅好画
2018/04/02 Python
Python实现繁体中文与简体中文相互转换的方法示例
2018/12/18 Python
通过python3实现投票功能代码实例
2019/09/26 Python
Python基于WordCloud制作词云图
2019/11/29 Python
PyQt5中向单元格添加控件的方法示例
2020/03/24 Python
HTML5+WebSocket实现多文件同时上传的实例
2016/12/29 HTML / CSS
仓管员岗位职责范文
2013/11/08 职场文书
优秀毕业大学生推荐信
2013/11/13 职场文书
一名老师的自我评价
2014/02/07 职场文书
关于抽烟的检讨书
2014/02/25 职场文书
人民调解员培训方案
2014/06/05 职场文书
2014年单位法制宣传日活动总结
2014/11/01 职场文书
2015年世界急救日宣传活动方案
2015/05/06 职场文书
python中opencv实现图片文本倾斜校正
2021/06/11 Python