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 相关文章推荐
jQuery EasyUI API 中文文档 - Tabs标签页/选项卡
Oct 01 Javascript
IE关闭时判断及AJAX注销案例学习
Feb 18 Javascript
AngularJS实现分页显示数据库信息
Jul 01 Javascript
学习vue.js计算属性
Dec 03 Javascript
Bootstrap 过渡效果Transition 模态框(Modal)
Mar 17 Javascript
代码详解Vuejs响应式原理
Dec 20 Javascript
玩转vue的slot内容分发
Sep 22 Javascript
VUE+Element环境搭建与安装的方法步骤
Jan 24 Javascript
JavaScript强制类型转换和隐式类型转换操作示例
May 01 Javascript
vue组件三大核心概念图文详解
May 30 Javascript
js实现QQ邮箱邮件拖拽删除功能
Aug 27 Javascript
vue中data里面的数据相互使用方式
Jun 05 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
利用PHP生成静态HTML文档的原理
2012/10/29 PHP
php获取qq用户昵称和在线状态(实例分析)
2013/10/27 PHP
PHP面向对象精要总结
2014/11/07 PHP
PHP中preg_match函数正则匹配的字符串长度问题
2015/05/27 PHP
Joomla数据库操作之JFactory::getDBO用法
2016/05/05 PHP
根据出生日期自动取得星座的js代码
2010/07/20 Javascript
javascript学习笔记(九)javascript中的原型(prototype)及原型链的继承方式
2011/04/12 Javascript
functional继承模式 摘自javascript:the good parts
2011/06/20 Javascript
JS 退出系统并跳转到登录界面的实现代码
2013/06/29 Javascript
通过正则表达式实现表单验证是否为中文
2014/02/18 Javascript
如何书写高质量jQuery代码(使用jquery性能问题)
2014/06/30 Javascript
sogou地图API用法实例教程
2014/09/11 Javascript
jQuery表单美化插件jqTransform使用详解
2015/04/12 Javascript
javascript HTML+CSS实现经典橙色导航菜单
2016/02/16 Javascript
20分钟成功编写bootstrap响应式页面 就这么简单
2016/05/12 Javascript
JS表格组件神器bootstrap table详解(强化版)
2016/05/26 Javascript
node.js 模块和其下载资源的镜像设置的方法
2018/09/06 Javascript
详解vue中的computed的this指向问题
2018/12/05 Javascript
微信小程序实现传递多个参数与事件处理
2019/08/12 Javascript
纯js+css实现仿移动端淘宝网站的弹出详情框功能
2019/12/29 Javascript
解决vue与node模版引擎的渲染标记{{}}(双花括号)冲突问题
2020/09/11 Javascript
keep-alive保持组件状态的方法
2020/12/02 Javascript
[49:12]完美世界DOTA2联赛PWL S2 Magma vs GXR 第二场 11.29
2020/12/02 DOTA
Python中os和shutil模块实用方法集锦
2014/05/13 Python
python中函数默认值使用注意点详解
2016/06/01 Python
qpython3 读取安卓lastpass Cookies
2016/06/19 Python
基于Python数据结构之递归与回溯搜索
2020/02/26 Python
Django分组聚合查询实例分享
2020/04/29 Python
Hotels.com日本:国外和海外住宿,酒店预订
2019/12/13 全球购物
银行学习十八大感想
2014/01/11 职场文书
2014年教师节寄语
2014/08/11 职场文书
2014年销售工作总结与计划
2014/12/01 职场文书
升职感谢信
2015/01/22 职场文书
幼儿园小班开学寄语
2015/05/27 职场文书
深入解析MySQL索引数据结构
2021/10/16 MySQL
微信小程序调用python模型
2022/04/21 Python