博客
关于我
手动实现apply、call、bind
阅读量:410 次
发布时间:2019-03-06

本文共 3753 字,大约阅读时间需要 12 分钟。

手动实现apply、call、bind

每个Function对象都存在apply()call()bind()方法,其作用都是可以在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。

apply

funct.apply(thisArg, [argsArray])

thisArg: 必选,在funct函数运行时使用的this值,this可能不是该方法看到的实际值,如果这个函数处于非严格模式下,则指定为nullundefined时会自动替换为指向全局对象,原始值会被包装。
argsArray: 可选,传递一个参数数组或者类数组对象,其中的数组元素将作为单独的参数传给funct函数,如果该参数的值为nullundefined,则表示不需要传入任何参数。
实现思路,类似于Function.prototype.apply(),同样将_apply()方法挂载到Function.prototype,使得函数对象能够直接调用,在调用funct._apply()时,在_apply()方法中的this指向的是funct对象,将此funct对象作为一个变量赋予将要绑定的对象的一个属性中,使用将要绑定的对象来调用这个funct,即可实现this指针指向将要绑定的对象,对于参数的处理,直接使用ES6Spread运算符将数组展开作为参数传递。

window.a = 1; // 定义一个全局变量var obj = {a: 2} // 定义一个对象用来绑定var funct = function(b, c) { console.log(this.a,b,c); return 1; }; // 定义一个函数用来执行funct(1, 2); // 1 1 2  // 直接执行,相当于window.funct(1, 2),this绑定于windowfunct.apply(obj, [1, 2]); // 2 1 2 // 使用apply将this绑定到obj对象Function.prototype._apply = function(base, args) { // 拓展Function原型    base = base || window; // 传递绑定的对象为null或undefined时指向window    base.fn = this; // 调用_apply时的this指向的是调用者也就是函数对象,将函数对象赋值给base对象的一个属性    var result = base.fn(...args); // 调用base.fn时,fn中的this指针指向的是base,并使用Spread操作符展开参数传参    delete base.fn; // 删除base对象的fn属性    return result; // 将返回值返回}funct._apply(obj, [1, 2]); // 2 1 2 // this绑定到了obj对象

call

funct.call(thisArg[, arg1[, arg2[, ...]]])

thisArg: 必选,在funct函数运行时使用的this值,this可能不是该方法看到的实际值,如果这个函数处于非严格模式下,则指定为nullundefined时会自动替换为指向全局对象,原始值会被包装。
arg1, arg2, ...: 可选,指定的参数列表。
实现思路,类似于Function.prototype.call(),同样将_call()方法挂载到Function.prototype,使得函数对象能够直接调用,在调用funct._call()时,在_call()方法中的this指向的是funct对象,将此funct对象作为一个变量赋予将要绑定的对象的一个属性中,使用将要绑定的对象来调用这个funct,即可实现this指针指向将要绑定的对象,对于参数的处理,使用ES6Rest操作符来接收剩余参数,使用ES6Spread运算符将数组展开作为参数传递。

window.a = 1; // 定义一个全局变量var obj = {a: 2} // 定义一个对象用来绑定var funct = function(b, c) { console.log(this.a,b,c); return 1; }; // 定义一个函数用来执行funct(1, 2); // 1 1 2  // 直接执行,相当于window.funct(1, 2),this绑定于windowfunct.call(obj, 1, 2); // 2 1 2 // 使用call将this绑定到obj对象Function.prototype._call = function(base, ...args) { // 拓展Function原型,使用Rest操作符接收剩余参数    base = base || window; // 传递绑定的对象为null或undefined时指向window    base.fn = this; // 调用_call时的this指向的是调用者也就是函数对象,将函数对象赋值给base对象的一个属性    var result = base.fn(...args); // 调用base.fn时,fn中的this指针指向的是base,并使用Spread操作符展开参数传参    delete base.fn; // 删除base对象的fn属性    return result; // 将返回值返回}funct._call(obj, 1, 2); // 2 1 2 // this绑定到了obj对象

bind

funct.bind(thisArg[, arg1[, arg2[, ...]]])

thisArg: 必选,调用绑定函数时作为this参数传递给目标函数的值,如果使用new运算符构造绑定函数,则忽略该值,当作为回调提供时,作为thisArg传递的任何原始值都将转换为object,如果bind函数的参数列表为空,或者thisArgnullundefined,执行作用域的this将被视为新函数的thisArg
arg1, arg2, ...: 可选,当目标函数被调用时,被预置入绑定函数的参数列表中的参数。
实现思路,类似于Function.prototype.bind(),同样将_bind()方法挂载到Function.prototype,使得函数对象能够直接调用,利用箭头函数在词法上绑定this值的特性,返回一个指定了this的函数,倘若不使用箭头函数,也可以将this值分配给封闭的变量来构建闭包,然后是类似于apply方法的实现,来绑定this到指定的对象。

window.a = 1; // 定义一个全局变量var obj = {a: 2} // 定义一个对象用来绑定var funct = function(b, c) { console.log(this.a,b,c); return 1; }; // 定义一个函数用来执行funct(1, 2); // 1 1 2  // 直接执行,相当于window.funct(1, 2),this绑定于windowvar bindFunct = funct.bind(obj, 1, 2); // 使用bind将this绑定到obj对象,bind方法返回一个原函数的拷贝,并拥有指定的this值和初始参数。bindFunct(); // 2 1 2 Function.prototype._bind = function(base, ...args1) { // 拓展Function原型,使用Rest操作符接收剩余参数    return (...args2) => { // 箭头函数不会生成自身作用域下的this,会从自己的作用域链的上一层继承this        base = base || window; // 传递绑定的对象为null或undefined时指向window        base.fn = this; // 调用箭头函数时的this指向的是调用者也就是函数对象,将函数对象赋值给base对象的一个属性        var result = base.fn(...args1, ...args2); // 调用base.fn时,fn中的this指针指向的是base,并使用Spread操作符展开参数传参        delete base.fn; // 删除base对象的fn属性        return result; // 将返回值返回    }}var _bindFunct = funct._bind(obj, 1, 2); // 绑定对象_bindFunct(); // 2 1 2

每日一题

https://github.com/WindrunnerMax/EveryDay

参考

https://www.jianshu.com/p/57a876fe66c8

转载地址:http://unckz.baihongyu.com/

你可能感兴趣的文章
MySQL 数据类型和属性
查看>>
mysql 敲错命令 想取消怎么办?
查看>>
Mysql 整形列的字节与存储范围
查看>>
mysql 断电数据损坏,无法启动
查看>>
MySQL 日期时间类型的选择
查看>>
Mysql 时间操作(当天,昨天,7天,30天,半年,全年,季度)
查看>>
MySQL 是如何加锁的?
查看>>
MySQL 是怎样运行的 - InnoDB数据页结构
查看>>
mysql 更新子表_mysql 在update中实现子查询的方式
查看>>
MySQL 有什么优点?
查看>>
mysql 权限整理记录
查看>>
mysql 权限登录问题:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)
查看>>
MYSQL 查看最大连接数和修改最大连接数
查看>>
MySQL 查看有哪些表
查看>>
mysql 查看锁_阿里/美团/字节面试官必问的Mysql锁机制,你真的明白吗
查看>>
MySql 查询以逗号分隔的字符串的方法(正则)
查看>>
MySQL 查询优化:提速查询效率的13大秘籍(避免使用SELECT 、分页查询的优化、合理使用连接、子查询的优化)(上)
查看>>
mysql 查询数据库所有表的字段信息
查看>>
【Java基础】什么是面向对象?
查看>>
mysql 查询,正数降序排序,负数升序排序
查看>>