手动实现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时指向windowbase.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时指向windowbase.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,会从自己的作用域链的上一层继承thisbase = base || window; // 传递绑定的对象为null或undefined时指向windowbase.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. JavaScript中的call、apply、bind深入理解

    一.函数的三种角色 首先要先了解在函数本身会有一些自己的属性,比如: length:形参的个数: name:函数名: prototype:类的原型,在原型上定义的方法都是当前这个类的实例的公有方法: ...

  2. 方法apply作用于对象sort时失败_浅析call、apply 与 bind

    点击上方蓝色字体轻松关注 前言 经典模式题:call.apply 与 bind的区别.来吧,今天搞一搞. call(thisArgs [,args...]) 该方法可以传递一个thisArgs参数和一 ...

  3. 理解js中的this指向以及call,apply,bind方法

    <script> function a(){var user = "追梦子";console.log(this.user); //undefinedconsole.lo ...

  4. call、apply、bind 用法和区别

    js 中,每个函数的原型都指向Function.prototype对象,因此,每个函数都会有apply,call,和bind方法,这些方法继承于Function,都是用于改变函数执行时的上下文,从而改 ...

  5. 微信小程序之apply和call ( 附示例代码和注释讲解) apply call  bind

    微信小程序开发交流qq群   173683895 相同点:作用是一样的,它们能劫持另外一个对象的方法,继承另外一个对象的属性: js中的call(), apply()和bind()是Function. ...

  6. apply call bind 简介

    Function.prototype.call(thisArg [, arg1, arg2, ...]) call() 简述 call() 方法 调用一个函数, 其具有一个指定的 this 值和分别地 ...

  7. JavaScript 中 call、apply和bind的用法区别

    ECMAScript 规范给所有函数都定义了 call 与 apply 两个方法,它们的应用非常广泛,它们的作用也是一模一样,只是传参的形式有区别而已. 其实是一个很简单的东西,认真看十分钟就从一脸懵 ...

  8. js之call,apply和bind的模拟实现

    了解call,apply和bind对于看一些源码以及封装一些工具有很大的作用. 如果想要了解并熟练使用它..就必须知道他的基本的实现原理. 一,基本用法 使用 let obj = {a: 18 }fu ...

  9. 记录call、apply、bind的源码

    记录一下call.apply.bind的源码,然后从根本上明白其用法. 都知道call.apply与bind的用法,call(this,...arguments).apply(this,[argume ...

最新文章

  1. 论一枚数据科学家的自我修养
  2. Xcode 6.x 上开发APP 兼容 iOS7
  3. anaconda3配置环境变量_阿里云ECS配置Jupyter Notebook
  4. php fpm xcache,php扩展xcache
  5. Android之解决Base64 encode中文乱码问题
  6. 记一次YY笔试中卡住得知识点
  7. [jQuery基础] jQuery动效
  8. C# 获得当前应用程序路径
  9. 面试题 丑数(10)
  10. GeeM2传奇引擎进入游戏出现白屏的解决办法
  11. 【Pytorch】model.train() 和 model.eval() 原理与用法
  12. 【css技巧】CSS filter的神奇用法 | 褪色|融合效果等
  13. rrpp协议如何修改_RRPP(快速环网保护协议)
  14. 循环语句—for/while/do...while
  15. 钉钉在线表格下载后子表内容空白无数据
  16. 书籍-传承至今的智慧载体
  17. excel转json操作
  18. 计算机科学和统计学AP,新航道解析:AP计算机科学A-标识符和类型
  19. 打开见识,保持努力,直到出类拔萃
  20. CoolWeather APP项目总结

热门文章

  1. 微信录音滑动撤销 html5,微信中这个被取消的功能悄悄上线了,将语音上滑即可转换成文字...
  2. 深入理解SpringBoot(3)
  3. redis优化查询的两种方式
  4. 基于centos6.5安装ElasticSearch
  5. CSS 笔记——盒子模型
  6. ZStack常见问题
  7. 艾默生网络能源的数据中心生意经
  8. 高级版本VS打开低版本VS工程,无法调试的问题
  9. Archlive新年第一棒: 基于2.6.37稳定内核的archlive20110107
  10. Lumia 800 升级 windows phone 7.8