手动实现apply、call、bind
手动实现apply、call、bind
每个Function
对象都存在apply()
、call()
、bind()
方法,其作用都是可以在特定的作用域中调用函数,等于设置函数体内this
对象的值,以扩充函数赖以运行的作用域。
apply
funct.apply(thisArg, [argsArray])
thisArg
: 必选,在funct
函数运行时使用的this
值,this
可能不是该方法看到的实际值,如果这个函数处于非严格模式下,则指定为null
或undefined
时会自动替换为指向全局对象,原始值会被包装。
argsArray
: 可选,传递一个参数数组或者类数组对象,其中的数组元素将作为单独的参数传给funct
函数,如果该参数的值为null
或undefined
,则表示不需要传入任何参数。
实现思路,类似于Function.prototype.apply()
,同样将_apply()
方法挂载到Function.prototype
,使得函数对象能够直接调用,在调用funct._apply()
时,在_apply()
方法中的this
指向的是funct
对象,将此funct
对象作为一个变量赋予将要绑定的对象的一个属性中,使用将要绑定的对象来调用这个funct
,即可实现this
指针指向将要绑定的对象,对于参数的处理,直接使用ES6
的Spread
运算符将数组展开作为参数传递。
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绑定于window
funct.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
可能不是该方法看到的实际值,如果这个函数处于非严格模式下,则指定为null
或undefined
时会自动替换为指向全局对象,原始值会被包装。
arg1, arg2, ...
: 可选,指定的参数列表。
实现思路,类似于Function.prototype.call()
,同样将_call()
方法挂载到Function.prototype
,使得函数对象能够直接调用,在调用funct._call()
时,在_call()
方法中的this
指向的是funct
对象,将此funct
对象作为一个变量赋予将要绑定的对象的一个属性中,使用将要绑定的对象来调用这个funct
,即可实现this
指针指向将要绑定的对象,对于参数的处理,使用ES6
的Rest
操作符来接收剩余参数,使用ES6
的Spread
运算符将数组展开作为参数传递。
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绑定于window
funct.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
函数的参数列表为空,或者thisArg
是null
或undefined
,执行作用域的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绑定于window
var 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
手动实现apply、call、bind的更多相关文章
- 自己手动用原生实现bind/call/apply
自己手动用原生实现bind/call/apply:https://www.cnblogs.com/LHLVS/p/10595784.html
- JS核心系列:浅谈 call apply 与 bind
在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...
- 深入理解 call,apply 和 bind
在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...
- 改变函数中的 this 指向——神奇的call,apply和bind及其应用
在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...
- 【THE LAST TIME】this:call、apply、bind
前言 The last time, I have learned [THE LAST TIME]一直是我想写的一个系列,旨在厚积薄发,重温前端. 也是给自己的查缺补漏和技术分享. 欢迎大家多多评论指点 ...
- js中call、apply和bind到底有什么区别?
介绍 在js中,每个函数的原型都指向Function.prototype对象(js基于原型链的继承).因此,每个函数都会有apply,call,和bind方法,这些方法继承于Function. 它们的 ...
- 【JS】306- 深入理解 call,apply 和 bind
作者:一像素 链接:https://www.cnblogs.com/onepixel/p/6034307.html 在JavaScript 中,call.apply 和 bind 是 Function ...
- js中的call()、apply()、bind()
js中的一个核心概念就是对this的理解,关于this前面也有说过,不过在有些情况下,还是需要手动去改变this的指向,这里总结一下,js中关于this操作的三种方法 call() apply() b ...
- 深入聚焦 call,apply 和 bind
在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...
- call,apply,bind的理解
call,apply,bind均是用于改变this指向. 三者相似之处: 1:都是用于改变函数的this指向. 2:第一个参数都是this要指向的对象. 3:都可以通过后面的参数进行对方法的传参. l ...
随机推荐
- WebApi的输出结果重写 OnActionExecuted
public override void OnActionExecuted(ActionExecutedContext context) { if (context.Exception != null ...
- Python Code_02
author : 写bug的盼盼 development time : 2021/8/27 19:59 变量定义 name = '阿哈' print(name) print('标识',id(name) ...
- [转帖]部署Alertmanager
https://flashcat.cloud/docs/content/flashcat-monitor/prometheus/alert/manager-install/ Alertmanager和 ...
- megacli_sw服务器Raid卡的设置过程
megacli_sw服务器的设置过程 背景 采购的申威服务器有四块硬盘, 第一台服务器在sdd上面安装了一个银河麒麟v10的系统 sda,sdb,sdc 三块硬盘没有进行raid设置, 直接还是用的J ...
- [转帖]PyCharm无法安装第三方模块,一直提示 updating list:time out 解决办法
Pycharm无法安装第三方模块解决办法: 1.打开pycharm的项目的venv文件夹 2.打开文件夹目录中的pyvenv文件 3.将文件中的include-system-site-packages ...
- [转帖]TaiShan v110 - Microarchitectures - HiSilicon
https://en.wikichip.org/wiki/hisilicon/microarchitectures/taishan_v110 Edit Values TaiShan v110 µa ...
- IIS 实现autoindex的简单方法 能够下载文件等.
之前使用nginx 的autoindex on 的参数 能够实现了 nginx的 目录浏览查看文件 但是那是linux上面的 windows 上面很多 使用的 其实是 iis的居多 然后看了下 其实也 ...
- 巧用GenericObjectPool创建自定义对象池
作者:京东物流 高圆庆 1 前言 通常一个对象创建.销毁非常耗时的时候,我们不会频繁的创建和销毁它,而是考虑复用.复用对象的一种做法就是对象池,将创建好的对象放入池中维护起来,下次再用的时候直接拿池中 ...
- css水平居中的5种几种方式
元素水平居中的第一种方式 子元素不需要宽度也可以 <div class="box"> <div class="son"> 我是内容 &l ...
- 【JS 逆向百例】W店UA,OB反混淆,抓包替换CORS跨域错误分析
关注微信公众号:K哥爬虫,持续分享爬虫进阶.JS/安卓逆向等技术干货! 声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后 ...