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 相关文章推荐
在线编辑器中换行与内容自动提取
Apr 24 Javascript
js计算两个时间之间天数差的实例代码
Nov 19 Javascript
JS获取表格内指定单元格html内容的方法
Mar 31 Javascript
javascript同步服务器时间和同步倒计时小技巧
Sep 24 Javascript
vue2.0设置proxyTable使用axios进行跨域请求的方法
Oct 19 Javascript
vue脚手架搭建过程图解
Jun 06 Javascript
select2 ajax 设置默认值,初始值的方法
Aug 09 Javascript
vue 父组件给子组件传值子组件给父组件传值的实例代码
Apr 15 Javascript
JavaScript中的相等操作符使用详解
Dec 21 Javascript
vue项目中自定义video视频控制条的实现代码
Apr 26 Javascript
在vue中使用Echarts利用watch做动态数据渲染操作
Jul 20 Javascript
JavaScript实现网页下拉菜单效果
Nov 20 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实现像JSP,ASP里Application那样的全局变量
2007/01/12 PHP
PHP编写RESTful接口
2016/02/23 PHP
thinkPHP中钩子的使用方法实例分析
2017/11/16 PHP
科讯商业版中用到的ajax空间与分页函数
2007/09/02 Javascript
TextArea设置MaxLength属性最大输入值的js代码
2012/12/21 Javascript
图片无缝滚动代码(向左/向下/向上)
2013/04/10 Javascript
jquery中键盘事件小结
2016/02/24 Javascript
JQuery解析XML数据的几个简单实例
2016/05/18 Javascript
详解vue父子模版嵌套案例
2017/03/04 Javascript
微信小程序 仿美团分类菜单 swiper分类菜单
2017/04/12 Javascript
vue如何引用其他组件(css和js)
2017/04/13 Javascript
vue-router路由参数刷新消失的问题解决方法
2017/06/17 Javascript
JS扩展String.prototype.format字符串拼接的功能
2018/03/09 Javascript
微信小程序仿朋友圈发布动态功能
2018/07/15 Javascript
在Vue项目中使用snapshot测试的具体使用
2019/04/16 Javascript
JSX在render函数中的应用详解
2019/09/04 Javascript
JS实现简单随机3D骰子
2019/10/24 Javascript
[00:33]DOTA2上海特级锦标赛 CDEC战队宣传片
2016/03/04 DOTA
python将图片文件转换成base64编码的方法
2015/03/14 Python
Python使用email模块对邮件进行编码和解码的实例教程
2016/07/01 Python
Django框架使用mysql视图操作示例
2019/05/15 Python
Python 实现数据结构-循环队列的操作方法
2019/07/17 Python
Numpy 多维数据数组的实现
2020/06/18 Python
使用gunicorn部署django项目的问题
2020/12/30 Python
python drf各类组件的用法和作用
2021/01/12 Python
纯html5+css3下拉导航菜单实现代码
2013/03/18 HTML / CSS
Book Depository欧盟:一家领先的国际图书零售商
2019/05/21 全球购物
物流仓储计划书
2014/01/10 职场文书
2014党员学习《反腐倡廉警示教育读本》思想汇报
2014/09/13 职场文书
文明礼貌主题班会
2015/08/14 职场文书
2016年班主任培训心得体会
2016/01/07 职场文书
学生会自荐信
2019/05/16 职场文书
z-index不起作用
2021/03/31 HTML / CSS
Java基础之this关键字的使用
2021/06/30 Java/Android
Nginx+Tomcat负载均衡集群的实现示例
2021/10/24 Servers
vue判断按钮是否可以点击
2022/04/09 Vue.js