var context = {id: 12};
function fun (name, age) {
console.log(this.id, name, age)
}

bind

bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。

 原生 bind
1. var a = fun.bind(context, 'bind');
2. a(1); // 12, 'bind', 1 :作为普通函数
3. new a('1'); // undefined, 'bind', '1' :作为构造函数

以上例子可以看出

     bind作为普通函数使用时,改变的this的指向,指向context对象;fun函数执行了;传入参数不确定,可以在第一步bind传值,也可以在第二步执行函数fun传值。

     bind最为构造函数使用时,不同点是this指向实例的对象。

bind的实现代码

Function.prototype.mybind = function (context) {
if (this && this.constructor !== Function) // 抛错
throw new Error("Function.prototype.mybind - what is trying to be bound is not callable");
// this =>绑定函数 fun
var self = this;
// 获取mybind函数从第二个参数到最后一个参数
var arg = Array.prototype.slice.call(arguments, 1);
function fbound() {
// 普通函数: this => window 构造函数: this => 实例对象
// 获取mybind返回函数传入的函数
var args = Array.prototype.slice.call(arguments);
self.apply(this instanceof self ? this : context, arg.concat(args));
}
var FNOP = function () {};
FNOP.prototype = this.prototype;
fbound.prototype = FNOP.prototype;
return fbound;
} var a = fun.mybind(context, 'mybind');
a('12') // a: 普通函数
var b = new a(12) // a: 构造函数 b: 实例对象

  兼容写法

Function.prototype.bind = Function.prototype.bind || function () {
……
};

call

  call() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。

原生 call
1. fun.call(context, 'call', 2) // 12, call, 2

  

call 的实现代码

Function.prototype.mycall = function (context) {
if (this && this.constructor !== Function)
throw new Error(this.name + ".mycall is not a function");
context = context || window;
context.fn = this;
var arg = [];
for (var i =1; i< arguments.length; i++) {
arg.push('arguments[' + i + ']');
}
eval('context.fn(' + arg + ')');
delete context.fn;
} fun.mycall(context, 'mycall', 3); // 12, 'mycall', 3

  

apply

apply与call的实现原理差不多,只是apply第二个参数是数组;

1. fun.apply(context, ['call', '4']) // 12, call, '4'

  

Function.prototype.myapply = function (context, arr) {
if (this && this.constructor !== Function)
throw new Error(this.name + ".myapply is not a function");
context = context || window;
context.fn = this;
var arrs = [];
if (arr && arr.constructor === Array) { // 判断第二个参数是数组类型
for (var i =0; i <arr.length; i++) {
arrs.push('arr[' + i + ']');
}
eval('context.fn(' + arrs + ')');
} else if (!arr) { // 第二个参数不传
delete context.fn();
} else { // 第二个参数不是数组类型
throw new Error ("CreateListFromArrayLike called on non-object");
}
delete context.fn;
} fun.myapply(context, ['myapply', 4]);

  


最新文章

  1. 基于SSH框架的网上商城的质量属性
  2. ueditor在使用requirejs时,报ZeroClipboard undefined错误
  3. raid知识
  4. 外部式css样式,写在单独的一个文件中
  5. linux学习记录 常用指令大全
  6. dll导入导出资源文件查看工具 InspectExe
  7. hdu_4539_郑厂长系列故事——排兵布阵(状压DP|最大团)
  8. 基于IDL 的WebRS系统设计图
  9. JavaScript 轻松创建级联函数
  10. delete和delete[]
  11. Unity User Group 北京站图文报道:《Unity虚拟现实实战技巧》
  12. Mplayer 的编译
  13. WGAN讲解
  14. Java并发编程的艺术&#183; 笔记(1)
  15. spring-boot log
  16. sc.exe用法详解
  17. box-shadow比较美观的阴影
  18. js对象属性名驼峰式转下划线
  19. Python基础+模块、异常
  20. js運算符

热门文章

  1. 转3xian之所在 (一位ACM大牛的博文)
  2. linux中的C里面使用pthread_mutex_t锁(转载)
  3. 点击button传递消息,但是页面不跳转的解决方法
  4. bzoj 2660: [Beijing wc2012]最多的方案【dp】
  5. bzoj 4521: [Cqoi2016]手机号码【数位dp】
  6. 【插件开发】—— 4 SWT编程须知
  7. Maven环境搭建操作记录
  8. 自动判断手机版和pc版
  9. AJPFX总结在循环中break与continue的区别
  10. Mac OS 下安装和配置 maven