call

call 方法使用一个函数执行的时候更改本身 this 指向,并传入一个或者多个参数。

var obj = {
name: '$call'
}
function _fun() {
console.log(this.name, ...arguments)
} _fun.call(obj, 'call1', 'call2', 'call3') // $call call1 call2 call3

内部实现原理:

Function.prototype.$$call = function (context) {
// 第一个参数为 this 指向值,如无则指向 window
context = context || window
// 将本身的函数保存下来,在后面需要执行,这一步 this 的指向已经指向了 context
context.fn = this
// 将后面传入的参数转为数组,取除第一个 this 指向剩下的所有参数
let args = [...arguments].slice(1)
// 执行函数本身,并将参数传入
let result = context.fn(...args)
// 销毁函数,避免作用域污染
delete context.fn
return result
}

apply

apply 方法同 call 一样使用一个函数执行的时候更改本身 this 指向,只是传参的时候只有一个,并且必须是数组(如果call与apply传参类型记不清,可以根据方法的第一个字母来区分,apply -> a(首字母) -> array)。

var obj = {
name: '$call'
}
function _fun() {
console.log(this.name, ...arguments)
} _fun.apply(obj, ['call1', 'call2', 'call3']) // $call call1 call2 call3

内部实现原理:

Function.prototype.$$apply = function (context) {
// 第一个参数为 this 指向值,如无则指向 window
context = context || window
// 将本身的函数保存下来,在后面需要执行,这一步 this 的指向已经指向了 context
context.fn = this
// 将后面传入的参数转为数组,取除第二个参数
let args = [...arguments][1]
// 如果第二个参数不是对象则报错
if (typeof args !== 'object') {
throw Error('CreateListFromArrayLike called on non-object')
return
}
// 执行函数本身,并将参数传入
let result = context.fn(...args)
// 销毁函数,避免作用域污染
delete context.fn
return result
}

bind

bind 方法与 call 和 apply 不同的点是后续的参数没有要求,但是 bind 会返回一个 this 指向已改变的函数,相同的是第一个参数就是 this 指向值

var obj = {
name: '$call'
}
function _fun() {
console.log(this.name, ...arguments)
} _fun.call(obj, ['call1'], 'call3')('call2') // $call ["call1"] call3 call2

内部实现原理:

Function.prototype.$$bind = function (context) {
// 取bind执行的时候除第一个后续的所有参数
let args = [...arguments].slice(1)
// 函数本身缓存
let _this = this
// 返回函数
return function () {
// 合并返回函数执行传入的参数
let bindArg = [...args, ...arguments]
// 再次调用时的函数本身执行
return _this.call(context, ...bindArg)
}
}

call,apply,bind的内部原理实现的更多相关文章

  1. 如何实现new,call,apply,bind的底层原理。

    new做了什么? new是用来实例化对象的,当new了一个对象后 1.创建一个新对象 2.将构造函数的作用域赋值给新对象(this指向新对象) 3.执行构造函数里面的代码(为这个新对象添加属性) 4. ...

  2. JavaScript内置一些方法的实现原理--new关键字,call/apply/bind方法--前戏

    new关键字,call/apply/bind方法都和this的绑定有关,在学习之前,首先要理解this. 一起来学习一下this吧 首先.this是一个对象. 对象很好理解,引用类型值,可以实现如th ...

  3. 前端面试 js 你有多了解call,apply,bind?

    函数原型链中的 apply,call 和 bind 方法是 JavaScript 中相当重要的概念,与 this 关键字密切相关,相当一部分人对它们的理解还是比较浅显,所谓js基础扎实,绕不开这些基础 ...

  4. 原生JS实现call,apply,bind函数

    1. 前言 使用原生JS实现call和apply函数,充分了解其内部原理.call和apply都是为了解决改变this的指向.作用都相同,只是传参的方式不同.除了第一个参数外,call可以接受一个参数 ...

  5. call(),apply(),bind()与回调

    1.call(),apply(),bind()方法 JavaScript 中通过call或者apply用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定 ...

  6. javascript-this,call,apply,bind简述2

    上节我们一起研究了this这个小兄弟,得出一个结论,this指向调用this所在函数(或作用域)的那个对象或作用域.不太理解的朋友可以看看上节的内容,这次我们主要探讨一下call(),apply(), ...

  7. 前端JS面试题汇总 Part 3 (宿主对象与原生对象/函数调用方式/call与apply/bind/document.write)

    原文:https://github.com/yangshun/front-end-interview-handbook/blob/master/questions/javascript-questio ...

  8. 你不知道的JavaScript--Item9 call(),apply(),bind()与回调

    1.call(),apply(),bind()方法 JavaScript 中通过call或者apply用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定 ...

  9. js 中arguments,call,apply,bind的使用

    //对于 arguments和this, 每个函数都有自己独有的arguments和this, 且不进行链式查找 //arguments是什么? //答:1:arguments是收到的实参副本 //2 ...

随机推荐

  1. FT-8900, 8800,7800 , FT-897, 857 e 817 连接中继板接线图

    FT-8900, 8800,7800 , FT-897, 857 e 817 等 车台支持Moto GM950i GM300(只适合接收) GM3688等

  2. repo 导出本地 git tag 给他人

    背景 使用 repo 管理了多个 git 仓库,有时需要将本地仓库的tag同步给其他人,但又不能直接推到远程(例如权限问题). 实际场景举例 本地复现了一个问题,需要让其他人回退到相同环境来排查. 本 ...

  3. STL中的string

    string常用函数 1.构造函数 string(const char *s); //用c字符串s初始化 string(int n,char c); //用n个字符c初始化 string类还支持默认构 ...

  4. 学习ASP.NET Core(10)-全局日志与xUnit系统测试

    上一篇我们介绍了数据塑形,HATEOAS和内容协商,并在制器方法中完成了对应功能的添加:本章我们将介绍日志和测试相关的概念,并添加对应的功能 一.全局日志 在第一章介绍项目结构时,有提到.NET Co ...

  5. 移动端响应式布局,rem动态更新

    (function(){ var fontSizeMatchDeviceWidth = function(){ var deviceWidth = document.documentElement.c ...

  6. Python基础——爬虫以及简单的数据分析

    目标:使用Python编写爬虫,获取链家青岛站的房产信息,然后对爬取的房产信息进行分析. 环境:win10+python3.8+pycharm Python库: import requests imp ...

  7. Ubuntu:E: Sub-process /usr/bin/dpkg returned an error code (1)

    Ubuntu系统安装软件时报以下错误: E: Sub-process /usr/bin/dpkg returned an error code (1) 解决: mv /var/lib/dpkg/inf ...

  8. (六)获取http状态码和处理返回结果

    int StatusCode = httpResponse.getStatusLine().getStatusCode(); 处理返回结果: /** * 处理返回结果 * @param respons ...

  9. postman切换环境

    原文链接:https://www.cnblogs.com/nicole-zhang/p/11498384.html 通常会有多个测试环境,针对同一个接口来说,可能只是域名有变化,此时可以添加postm ...

  10. 【JMeter_20】JMeter逻辑控制器__事务控制器<Transaction Controller>

    事务控制器<Transaction Controller> 业务逻辑: 这个控制器在在业务控制上并没有什么特殊逻辑,可以理解为在简单控制器的基础上添加了统计的功能,当所有子节点全部成功则成 ...