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 相关文章推荐
可拖动窗口,附带鼠标控制渐变透明,开启关闭功能
Jun 26 Javascript
js的event详解。
Sep 06 Javascript
jQuery使用手册之三 CSS操作
Mar 24 Javascript
JavaScript 动态添加表格行 使用模板、标记
Oct 24 Javascript
Easy.Ajax 部分源代码 支持文件上传功能, 兼容所有主流浏览器
Feb 24 Javascript
.net,js捕捉文本框回车键事件的小例子(兼容多浏览器)
Mar 11 Javascript
jquery判断单选按钮radio是否选中的方法
May 05 Javascript
javascript常用经典算法详解
Jan 11 Javascript
webstorm中vue语法的支持详解
May 09 Javascript
Jquery Datatables的使用详解
Jan 30 jQuery
vue router-link 默认a标签去除下划线的实现
Nov 06 Javascript
vue打开新窗口并实现传参的图文实例
Mar 04 Vue.js
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
Terran兵种对照表
2020/03/14 星际争霸
PHP防盗链代码实例
2014/08/27 PHP
PHP.ini安全配置检测工具pcc简单介绍
2015/07/02 PHP
postfixadmin忘记密码后的修改密码方法详解
2016/07/20 PHP
php fread读取文件注意事项
2016/09/24 PHP
Javascript 更新 JavaScript 数组的 uniq 方法
2008/01/23 Javascript
location.href 在IE6中不跳转的解决方法与推荐使用代码
2010/07/08 Javascript
深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP
2012/01/15 Javascript
在jQuery ajax中按钮button和submit的区别分析
2012/10/07 Javascript
JavaScript动态创建link标签到head里的方法
2014/12/22 Javascript
jquery实现select选择框内容左右移动代码分享
2015/11/21 Javascript
jQuery animate easing使用方法图文详解
2016/06/17 Javascript
jQuery图片拖动组件Dropzone用法示例
2017/01/17 Javascript
js实现模糊匹配功能
2017/02/15 Javascript
Angular.js项目中使用gulp实现自动化构建以及压缩打包详解
2017/07/19 Javascript
vue-cli2与vue-cli3在一台电脑共存的实现方法
2019/09/25 Javascript
JS实现导航栏楼层特效
2020/01/01 Javascript
node.js基础知识汇总
2020/08/25 Javascript
Python天气预报采集器实现代码(网页爬虫)
2012/10/07 Python
python实现的正则表达式功能入门教程【经典】
2017/06/05 Python
Django中间件工作流程及写法实例代码
2018/02/06 Python
python抓取网页内容并进行语音播报的方法
2018/12/24 Python
Pytorch基本变量类型FloatTensor与Variable用法
2020/01/08 Python
python误差棒图errorbar()函数实例解析
2020/02/11 Python
解决django migrate报错ORA-02000: missing ALWAYS keyword
2020/07/02 Python
详解Python中的路径问题
2020/09/02 Python
python网络爬虫实现发送短信验证码的方法
2021/02/25 Python
使用html2canvas实现浏览器截图的示例代码
2018/01/26 HTML / CSS
比利时香水网上商店:NOTINO
2018/03/28 全球购物
3D空间设计学生找工作的自我评价
2013/10/28 职场文书
离婚协议书范本样本
2014/08/19 职场文书
机械工程及自动化专业求职信
2014/09/03 职场文书
2015年公司新年寄语
2014/12/08 职场文书
2015年个人工作总结报告
2015/04/25 职场文书
辩论赛开场白大全(主持人+辩手)
2015/05/29 职场文书
Python内置包对JSON文件数据进行编码和解码
2022/04/12 Python