手动实现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绑定于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可能不是该方法看到的实际值,如果这个函数处于非严格模式下,则指定为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绑定于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函数的参数列表为空,或者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绑定于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的更多相关文章

  1. 自己手动用原生实现bind/call/apply

    自己手动用原生实现bind/call/apply:https://www.cnblogs.com/LHLVS/p/10595784.html

  2. JS核心系列:浅谈 call apply 与 bind

    在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...

  3. 深入理解 call,apply 和 bind

    在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...

  4. 改变函数中的 this 指向——神奇的call,apply和bind及其应用

    在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...

  5. 【THE LAST TIME】this:call、apply、bind

    前言 The last time, I have learned [THE LAST TIME]一直是我想写的一个系列,旨在厚积薄发,重温前端. 也是给自己的查缺补漏和技术分享. 欢迎大家多多评论指点 ...

  6. js中call、apply和bind到底有什么区别?

    介绍 在js中,每个函数的原型都指向Function.prototype对象(js基于原型链的继承).因此,每个函数都会有apply,call,和bind方法,这些方法继承于Function. 它们的 ...

  7. 【JS】306- 深入理解 call,apply 和 bind

    作者:一像素 链接:https://www.cnblogs.com/onepixel/p/6034307.html 在JavaScript 中,call.apply 和 bind 是 Function ...

  8. js中的call()、apply()、bind()

    js中的一个核心概念就是对this的理解,关于this前面也有说过,不过在有些情况下,还是需要手动去改变this的指向,这里总结一下,js中关于this操作的三种方法 call() apply() b ...

  9. 深入聚焦 call,apply 和 bind

    在JavaScript 中,call.apply 和 bind 是 Function 对象自带的三个方法,这三个方法的主要作用是改变函数中的 this 指向,从而可以达到`接花移木`的效果.本文将对这 ...

  10. call,apply,bind的理解

    call,apply,bind均是用于改变this指向. 三者相似之处: 1:都是用于改变函数的this指向. 2:第一个参数都是this要指向的对象. 3:都可以通过后面的参数进行对方法的传参. l ...

随机推荐

  1. [转帖]java乱码 java使用的编码是utf-8还是utf-16还是unicode

    简单介绍编码 Unicode:是容纳世界所有文字符号的国标标准编码,使用四个字节为每个字符编码 UTF:是英文 Unicode Transformation Format 的缩写,意为把 Unicod ...

  2. SQLServer数据库优化学习-总结

    SQLServer数据库优化学习-总结 背景 各种能力都需要提升. 最近总是遇到SQLServer的问题 趁着周末进行一下学习与提高. 安装与优化 1. 数据库必须安装 64位, 不要安装成32位的版 ...

  3. [转帖]Fluentd 的优缺点

    https://zhuanlan.zhihu.com/p/129375187   以前在不少场合浅度使用过 Fluentd,将日志汇聚到一个地方.它给我的大体印象是 简单且能解决问题 直到最近遇到一个 ...

  4. [转帖]Jmeter跨线程组传参

    https://www.cnblogs.com/a00ium/p/10462576.html   我们知道,同一线程组中可以通过"正则表达式提取器"获取其中一个取样器的响应结果中的 ...

  5. Linux执行SQLSERVER语句的简单方法

    背景 因为WTF的原因.经常有人让执行各种乱七八槽的删除语句 因为产品支持了10多种数据库. 这个工作量非常复杂. 为了简单起见,想着能够批量执行部分SQL. 其他的都处理过了,但是SQLSERVER ...

  6. date的命令使用.

    date命令的使用 1.直接用date命令显示日期时间 在命令行中输入date然后回车,显示结果"Wed Aug 7 08:58:07 CST 2019".这是系统根据设定的时区显 ...

  7. 《Javascript高级程序设计》读书笔记——函数与闭包

    函数与闭包 函数创建 创建函数有两种方式,第一种是函数声明.函数声明有一个很重要的特征就是函数声明提升(function declaration hoisting),意思是在执行代脚本前会先读取所有的 ...

  8. 分布式日志追踪ID实战 | 京东物流技术团队

    本文通过介绍分布式应用下各个场景的全局日志ID透传思路,以及介绍分布式日志追踪ID简单实现原理和实战效果,从而达到通过提高日志查询排查问题的效率. 背景 开发排查系统问题用得最多的手段就是查看系统日志 ...

  9. js快速获取当前时间并且返回想要的格式

    function backCurrentTime (type) { let currentTime=new Date( new Date() + 8 * 3600 * 1000 ).toJSON(). ...

  10. 在K8S中各个组件及其作用?

    Kubernetes(简称K8s)是一个强大的容器编排系统,其主要组件及其作用如下: kube-apiserver: 集群的主入口点,提供了RESTful API接口供用户或内部组件与集群进行交互.它 ...