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. java代码(2)---Java8 Stream

    stream Java8新特性Stream流,那Stream表达式到底是什么呢,为什么可以使你的代码更加整洁而且对集合的操作效率也会大大提高? 一.概述 1.什么是Stream Stream是一种可供 ...

  2. FTM-100DR、FTM-400DR、FTM-400XDR和DR-1X 连接MMDVM中继板接线图BG7IYN

  3. /etc/alternatives

    如何安装一个可执行程序 一般来说我们一个可执行程序,可能在多个路径下,比如在opt路径下,或者在自己的home下. 当要达到在系统的任意路径下敲击该命令,都可执行的话,一般要将该可执行命令的路径加入到 ...

  4. OSI七层模型及各层作用

    物理层:建立.维护.断开物理连接 数据链路层:该层的作用包括了物理地址寻址,数据的成帧,流量控制,数据的检错,重发等.该层控制网络层与物理层之间的通信,解决的是所传输数据的准确性的问题.为了保证传输, ...

  5. 521.最长特殊序列 I

    2020-05-14 最长特殊序列 I 给你两个字符串,请你从这两个字符串中找出最长的特殊序列. 「最长特殊序列」定义如下:该序列为某字符串独有的最长子序列(即不能是其他字符串的子序列). 子序列 可 ...

  6. redis 的简明教程

    redis 结合ssm使用 一.Redis使用 1.jedis操作redis非关系型数据库 2.spring 集成redis 二.两者区别: 一.Redis使用 1.jedis操作redis非关系型数 ...

  7. 【Android】使用Appium+python控制真机,碰到的问题以及处理(持续更新)

    问题: selenium.common.exceptions.WebDriverException: Message: A new session could not be created. (Ori ...

  8. 从零开始的Spring Boot(4、Spring Boot整合JSP和Freemarker)

    Spring Boot整合JSP和Freemarker 写在前面 从零开始的Spring Boot(3.Spring Boot静态资源和文件上传) https://www.cnblogs.com/ga ...

  9. .NETCore微服务探寻(一) - 网关

    前言 一直以来对于.NETCore微服务相关的技术栈都处于一个浅尝辄止的了解阶段,在现实工作中也对于微服务也一直没有使用的业务环境,所以一直也没有整合过一个完整的基于.NETCore技术栈的微服务项目 ...

  10. Tensorflow报错:OMP: Error #15: Initializing libiomp5.dylib, but found libiomp5.dylib already initialized.

    参考: https://github.com/dmlc/xgboost/issues/1715 解决方法: I solved it with 'conda install nomkl'.