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 相关文章推荐
用JavaScript脚本实现Web页面信息交互
Dec 21 Javascript
js document.write()使用介绍
Feb 21 Javascript
jQuery满屏焦点图左右滚动特效代码分享
Sep 07 Javascript
开源免费天气预报接口API及全国所有地区代码(国家气象局提供)
Dec 26 Javascript
javascript 单例模式详解及简单实例
Feb 14 Javascript
纯js实现html转pdf的简单实例(推荐)
Feb 16 Javascript
Node.js+ES6+dropload.js实现移动端下拉加载实例
Jun 01 Javascript
Angular2 组件交互实例详解
Aug 24 Javascript
vue watch自动检测数据变化实时渲染的方法
Jan 16 Javascript
js实现左右两侧浮动广告
Jul 09 Javascript
Vue中使用clipboard实现复制功能
Sep 05 Javascript
微信小程序新闻网站详情页实例代码
Jan 10 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编写一个简单的路由类
2011/04/13 PHP
如何使用php输出时间格式
2013/08/31 PHP
php 使用GD库为页面增加水印示例代码
2014/03/24 PHP
ThinkPHP的SAE开发相关注意事项详解
2016/10/09 PHP
php利用云片网实现短信验证码功能的示例代码
2017/11/18 PHP
PHP实现UTF8二进制及明文字符串的转化功能示例
2017/11/20 PHP
Javascript实现的分页函数
2007/02/07 Javascript
JavaScript 学习点滴记录
2009/04/24 Javascript
Prototype Date对象 学习
2009/07/12 Javascript
Javascript 中介者模式实例
2009/12/16 Javascript
最短的javascript:地址栏载入脚本代码
2011/10/13 Javascript
JavaScript中常用的运算符小结
2012/01/18 Javascript
用js的for循环获取radio选中的值
2013/10/21 Javascript
JQuery中两个ul标签的li互相移动实现方法
2015/05/18 Javascript
JavaScript调用浏览器打印功能实例分析
2015/07/17 Javascript
JavaScript操作HTML元素和样式的方法详解
2015/10/21 Javascript
基于jQuery实现拖拽图标到回收站并删除功能
2015/11/25 Javascript
jquery中ajax处理跨域的三大方式
2016/01/05 Javascript
一些实用性较高的js方法
2016/04/19 Javascript
jquery  实现轮播图详解及实例代码
2016/10/12 Javascript
JS实现仿饿了么在浏览器标签页失去焦点时网页Title改变
2017/06/01 Javascript
Vue v2.5 调整和更新不完全问题
2017/10/24 Javascript
vue安装和使用scss及sass与scss的区别详解
2018/10/15 Javascript
python实现12306抢票及自动邮件发送提醒付款功能
2018/03/08 Python
python 解决tqdm模块不能单行显示的问题
2020/02/19 Python
解决Python paramiko 模块远程执行ssh 命令 nohup 不生效的问题
2020/07/14 Python
css3 flex实现div内容水平垂直居中的几种方法
2020/03/27 HTML / CSS
html5 postMessage前端跨域并前端监听的方法示例
2018/11/01 HTML / CSS
Moda Italia荷兰:意大利男士服装
2019/08/31 全球购物
List, Set, Map是否继承自Collection接口?
2016/05/16 面试题
银行实习的自我鉴定
2013/12/10 职场文书
阳光体育活动总结
2014/04/30 职场文书
应用心理学专业求职信
2014/08/04 职场文书
委托书范本
2014/09/13 职场文书
如何撰写出一份完美的商业计划书?
2019/07/12 职场文书
不知如何爱孩子,这些方法教会您
2019/08/06 职场文书