首先,三者第一个参数都为this指向

区别

bind返回的是一个函数体

call和apply会直接执行,但是call参数需要一个一个进行传递,apply的第二个参数是一个数组

实现

bind

简单实现

Function.prototype.myBind = function(context){
self = this; //保存this,即调用bind方法的目标函数
return function(){
return self.applay(context, [...arguments]);
};
};

考虑到函数柯里化的实现

Function.prototype.myBind = function(context){
// 使用闭包存下初始参数
var args = Array.prototype.slice.call(arguments, 1),
self = this;
return function() {
// 再次调用时
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return self.apply(context,finalArgs);
};
};

考虑构造函数的实现

Function.prototype.myBind = function(context){
// 判断是否为函数
if(typeof this !== 'function') {
throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
}
var args = Array.prototype.slice(arguments, 1);
self = this;
bound = function() {
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
// 判断this,如果是,则传递this即实例化的对象。
return self.apply((this instanceof F ? this : context), finalArgs);
};
// 处理原型链
let F = function(){};
F.prototype = self.prototype;
bound.prototype = new F(); retrun bound;
};

call

思路

// 要实现这个效果
var foo ={
value:1
}
function bar(){
console.log(this.value)
}
bar.call(foo);// // 相当于做如下事情
var foo = {
value: 1,
bar: function() {
console.log(this.value)
}
};
foo.bar(); //

​实现

Function.Prototype.myCall = function(context) {
// this 参数可以传 null,当为 null 的时候,视为指向 window
var context = context || window;
context.fn = this;
// 对参数进行处理
var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
args.push(arguments[i]);
}
let result = arguments.length>0 ? context.fn(...args) : context.fn();
delete context.fn;
return result;
}

apply

Function.Prototype.myApply = function(context, arr) {
// this 参数可以传 null,当为 null 的时候,视为指向 window
var context = context || window;
context.fn = this;
let result = arr.length>0 ? context.fn(...arr) : context.fn();
delete context.fn;
return result;
}

参考自

MDN中对bind的实现

https://blog.csdn.net/weixin_34250709/article/details/92426126

https://zhuanlan.zhihu.com/p/48081913

最新文章

  1. vs2013_arcgis_developer_kit_101_install
  2. iOS 证书申请和使用详解(详细版)
  3. (7)redis pipeline
  4. hdu3308 线段树——区间合并
  5. Boost.Any
  6. ASP.NET MVC 3 Razor Views in SharePoint
  7. JavaScript经典面试题系列
  8. Java equals的一个坑
  9. CCF考试真题题解
  10. 机器学习之决策树(ID3 、C4.5算法)
  11. centos安装实用总结
  12. centos7生产环境下openssh升级
  13. Linux虚拟机上安装redis
  14. [CF490F]Treeland Tour(线段树合并)
  15. 【JMeter】JMeter如何输出测试报告
  16. 虚函数后面的const=0
  17. Gym 100646 Problem E: Su-Su-Sudoku 水题
  18. java 读取execl文件
  19. CentOS和RedHat等系列系统 yum源配置、时间同步
  20. C#结构体+结构体与类的区别

热门文章

  1. PythonCrashCourse 第九章习题
  2. C# 中生成随机数
  3. consul、eureka、nacos对比
  4. ZK的watch机制
  5. Java数据结构——树、二叉树的理论知识汇总
  6. 手写Promise简易版
  7. MPI组操作
  8. springboot-swagger配置
  9. 8.深入k8s:资源控制Qos和eviction及其源码分析
  10. openCV - 1. 加载、修改、保存图像