记录一下call、apply、bind的源码,然后从根本上明白其用法。

都知道call、apply与bind的用法,call(this,...arguments)、apply(this,[arguments])、var fn = bind(this, ...arguments);fn(...newarguments);

call和apply都是立即执行,只是传参数形式不一样,call参数一字排开,apply参数是数组,bind绑定之后返回一个新函数但是并不立即执行,需要额外调用的时候才执行,并且,绑定的时候可以额外传参数,执行的时候也可以额外传参数。

call和apply执行的本质是,往要绑定的context对象下添加该函数,然后执行,最后将属性删除。当context值为null,或者undefined时,非严格模式下,它将替换为window或者global全局变量。

Function.prototype.call = function (context) {
var context = context || window;
context.fn = this; var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
args.push('arguments[' + i + ']');
} var result = eval('context.fn(' + args +')'); delete context.fn
return result;
}
Function.prototype.apply = function (context, arr) {
var context = Object(context) || window;
context.fn = this; var result;
if (!arr) {
result = context.fn();
}
else {
var args = [];
for (var i = 0, len = arr.length; i < len; i++) {
args.push('arr[' + i + ']');
}
result = eval('context.fn(' + args + ')')
} delete context.fn
return result;
}

bind因为不会立刻执行,而是返回一个函数,一般情况下,该函数执行时的this指向绑定的对象。而麻烦的是JS中该函数还可以通过new来实例化,而实例化之后的this要指向新创建的对象,不能再跟着绑定的对象走了,所以该函数内部对this进行了额外处理,看它是否是通过new创建的实例,如果是通过new创建的实例,this对象指向新创建的new对象实例。

if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "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
? this
: oThis || this,
aArgs.concat(Array.prototype.slice.call(arguments)));
}; fNOP.prototype = this.prototype;
fBound.prototype = new fNOP(); return fBound;
};
}

记录call、apply、bind的源码的更多相关文章

  1. WeMall微商城源码报名插件Apply的主要源码

    WeMall微信商城源码报名插件Apply,用于商城的签到系统,分享了部分比较重要的代码,供技术员学习参考 AdminController.class.php <?php namespace A ...

  2. 记录小白实习生的HashMap源码 put元素 的学习和一些疑问

    首先看HashMap存储结构 transient Node<K,V>[] table; static class Node<K,V> implements Map.Entry& ...

  3. PackageManagerService 学习记录 基于7.1.1源码

    参考: http://blog.csdn.net/innost/article/details/47253179 http://blog.csdn.net/gaugamela/article/deta ...

  4. bind方法源码

    'use strict'; module.exports = function bind(fn, thisArg) { return function wrap() { var args = new ...

  5. 【记录】SQL注入过滤源码分享

    $id=check_addslashes($_GET['id']);$id= preg_replace('/o*r/i',"", $id); //strip out OR (non ...

  6. 编译CM13源码添加来去电归属地 SudaMod开源项目,查看commit提交记录

    这个问题纠结了很多时间,感谢苏打先森@Sudamod的开源项目. 大家知道CM13是没有来去点归属地的,就算有那也是google,对于中国人不适用,所以这里把方法贡献出来. 1.与通话有关的app D ...

  7. nodeJS之eventproxy源码解读

    1.源码缩影 !(function (name, definition) { var hasDefine = typeof define === 'function', //检查上下文环境是否为AMD ...

  8. 想读Spring源码?先从这篇「 极简教程」开始吧...

    为什么要阅读源码?这是一个有趣的问题,类似的问题还有,为什么要看书?为什么要爬山? 这也是一个哲学问题,我想每个人都有不同的答案,下面我是对阅读源码好处的一些思考. (PS:也欢迎你在评论区留言补充) ...

  9. MyBatis源码分析-MyBatis初始化流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

随机推荐

  1. Flexible实现H5移动端适配小demo

    前言 看了宇哥关于移动端适配的分享后,加上目前公司项目也需要做移动端适配,今天就抽空搞了搞.目前业界还是比较推崇手淘使用"rem+viewport"的解决方案,今天自己模仿手淘fl ...

  2. R的操作入门熟悉

    产生向量: a=c(1,2,3) //产生 1,2,3向量 a=1:10-1 //产生 0 - 9数字 a=seq(5,20,by=2) // 以2增长 a=seq(5,120,length=10) ...

  3. SpringMVC 集成 JWT验证方式

    JWT官网: https://jwt.io/ 这里以java的ssm框架为例,集成jwt. 1.pom.xml 导入jwt的包 <!-- jwt --> <dependency> ...

  4. 20、FlyWeight 享元模式

    池化的思想 1.Flyweight享元模式 运用共享技术有效地支持大量细粒度对象的复用.系统只使用少量的对象,而这些对象都很相似,状态变化很小,可以实现对象的多次复用.由于享元模式要求能够共享的对象必 ...

  5. C# Thread.Join的报错情形——论执行完的线程能够成功执行Join吗

    结论: 能, 执行完的线程调用Join不会抛出错误. Thread.Join()是什么? Join()函数用于阻塞地等待线程结束, 其行为是在线程A中调用了线程B的Join()后, 线程A将一直阻塞在 ...

  6. C - 一个C语言猜字游戏

    下面是一个简陋的猜字游戏,玩了一会儿,发现自己打不过自己写的游戏,除非赢了就跑,最高分没有过1000. 说明:srand(time(NULL))和rand(),srand,time和rand都是函数, ...

  7. CUDA线程、线程块、线程束、流多处理器、流处理器、网格概念的深入理解

    一.与CUDA相关的几个概念:thread,block,grid,warp,sp,sm. sp: 最基本的处理单元,streaming processor  最后具体的指令和任务都是在sp上处理的.G ...

  8. Homekit_人体感应器

    前置需求: 苹果手机一台 Homekit人体感应一台 USB供电线一根 这款产品内置人体红外感应器,使用圆环设计,增大了其接触面积,使感应变得更加灵敏,重量轻,方便将其粘贴到墙上,同时支持二次开发,如 ...

  9. Centos7修改用户名

    系统原来的用户lou,改为scrapy,要改以下个地方,注:没有修改对应密码 1.   # vi /etc/passwd 修改其中的用户名部分.用户组部分.主目录部分2.  修改用户组的配置文件 # ...

  10. JavaScript学习系列博客_8_JavaScript中的关系运算符、赋值运算符

    关系运算符 - 关系运算符用来比较两个值之间的关系的 >.<.<=.>= 先说这四个.如果关系成立则返回true,关系不成立则返回false. - 如果比较的两个值是非numb ...