原生javascript实现call、apply和bind的方法
2024-08-26 11:58:11
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]);
最新文章
- 基于SSH框架的网上商城的质量属性
- ueditor在使用requirejs时,报ZeroClipboard undefined错误
- raid知识
- 外部式css样式,写在单独的一个文件中
- linux学习记录 常用指令大全
- dll导入导出资源文件查看工具 InspectExe
- hdu_4539_郑厂长系列故事——排兵布阵(状压DP|最大团)
- 基于IDL 的WebRS系统设计图
- JavaScript 轻松创建级联函数
- delete和delete[]
- Unity User Group 北京站图文报道:《Unity虚拟现实实战技巧》
- Mplayer 的编译
- WGAN讲解
- Java并发编程的艺术&#183; 笔记(1)
- spring-boot log
- sc.exe用法详解
- box-shadow比较美观的阴影
- js对象属性名驼峰式转下划线
- Python基础+模块、异常
- js運算符
热门文章
- 转3xian之所在 (一位ACM大牛的博文)
- linux中的C里面使用pthread_mutex_t锁(转载)
- 点击button传递消息,但是页面不跳转的解决方法
- bzoj 2660: [Beijing wc2012]最多的方案【dp】
- bzoj 4521: [Cqoi2016]手机号码【数位dp】
- 【插件开发】—— 4 SWT编程须知
- Maven环境搭建操作记录
- 自动判断手机版和pc版
- AJPFX总结在循环中break与continue的区别
- Mac OS 下安装和配置 maven