手动实现bind、call、apply方法

智数探云人
• 阅读 2590
转载请注明出处

bind()

bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被bind的第一个参数指定,其余的参数将作为新函数的参数供调用时使用。

语法:
function.bind(thisArg[,arg1[,arg2[, ...]]])
示例:
var module = {
  x: 42,
  getX: function() {
    return this.x;
  }
}

var unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined

var boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
以下是对 bind() 的一个实现:
Function.prototype.bind = function(context) {
  if (typeof this !== 'function') {
    throw new TypeError('Error')
  }
  let _this = this
  let args = [...arguments].slice(1)
  return function F() {
    // 判断是否被当做构造函数使用
    if (this instanceof F) {
      return _this.apply(this, args.concat([...arguments]))
    }
    return _this.apply(context, args.concat([...arguments]))
  }
}

apply()

apply() 方法调用一个具有给定this值的函数,以及作为一个数组(或类似数组对象)提供的参数。

语法:
func.apply(thisArg, [argsArray])
示例:
var numbers = [5, 6, 2, 3, 7];

var max = Math.max.apply(null, numbers);

console.log(max);
// expected output: 7

var min = Math.min.apply(null, numbers);

console.log(min);
// expected output: 2
以下是对apply() 的一个实现:
Function.prototype.apply = function(context) {
  // context就是apply的第一个参数,在这里也就是obj
  // 判断是否是undefined和null
  if (typeof context === 'undefined' || context === null) {
    context = window
  }
  // this也就是调用apply的函数 把函数赋值给context下面的一个键,这里是fn
  context.fn = this
  // arguments就是传进来的参数
  let args = arguments[1]
  let result
  if (args) {
      result = context.fn(...args)
  } else {
      result = context.fn()
  }
  delete context.fn
  return result
}
let test = function (sex) {
    console.log(this.name + sex)
}
let obj = {
    name: '我是'
}
test.apply(obj, ['test'])

call()

call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。

语法:
fun.call(thisArg, arg1, arg2, ...)
示例:
function Product(name, price) {
  this.name = name;
  this.price = price;
}

function Food(name, price) {
  Product.call(this, name, price);
  this.category = 'food';
}

console.log(new Food('cheese', 5).name);
// expected output: "cheese"
以下是对 call() 的一个实现:
Function.prototype.call = function(context) {
  // context就是call的第一个参数,在这里也就是obj
  // 判断是否是undefined和null
  if (typeof context === 'undefined' || context === null) {
    context = window
  }
  // this也就是调用call的函数 把函数赋值给context下面的一个键,这里是fn
  context.fn = this
  // arguments就是传进来的参数
  let args = [...arguments].slice(1)
  let result = context.fn(...args)
  delete context.fn
  return result
}
let test = function (sex) {
    console.log(this.name + sex)
}
let obj = {
    name: '我是'
}
test.call(obj, 'test')

参考资料


欢迎浏览我的个人网站
点赞
收藏
评论区
推荐文章
Dax Dax
3年前
JavaScript中call()、apply()、bind()的用法
call()apply()bind()都是用来更改this的指向的其中bind()返回的是一个函数,必须执行才行传参差异:call、bind、apply这三个函数的第一个参数都是this的指向对象,第二个参数差别就来了:call的参数是直接放进去的,第二第三第n个参数全都用逗号分隔,直接放到后面obj.myFun.call(db,'
巴拉米 巴拉米
4年前
bind、call、apply 区别?如何实现一个bind?
一、作用call、apply、bind作用是改变函数执行时的上下文,简而言之就是改变函数运行时的this指向那么什么情况下需要改变this的指向呢?下面举个例子var name"lucy";const obj{    name:"martin",    say:function (){        co
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
LinMeng LinMeng
4年前
call、apply、bind三者为改变this指向的方法。
共同点:第一个参数都为改变this的指针。若第一参数为null/undefined,this默认指向window差异点如下:1.call(无数个参数)第一个参数:改变this指向第二个参数:实参使用之后会自动执行该函数functionfn(a,b,c){console.log(this,abc);//this指
LinMeng LinMeng
3年前
面试题汇总
2021/10/30pfyh1、举例说几个ES6新特性2、map和filter的区别3、浏览器缓存机制4、vue渲染机制5、生命周期钩子函数6、组件传值7、箭头函数的特点/this指向/有没有arguments/如何获取入参8、虚拟DOM树9、Diff算法10、Vuex11、vue的两种路由模式hash和history的特点12、bind,call,appl
Easter79 Easter79
3年前
sql:mysql:函数:TIMESTAMPDIFF函数实现TimeStamp字段相减,求得时间差
<divclass"htmledit\_views"id"content\_views"<p&nbsp;函数内指定是minute,则最终结果value值的单位是分钟,如果函数内指定为hours,则最终结果value值单位为小时。</p<preclass"has"name"code"<codeclass"hljssql"<
Stella981 Stella981
3年前
React Hooks实现异步请求实例—useReducer、useContext和useEffect代替Redux方案
<blockquote本文是学习了2018年新鲜出炉的ReactHooks提案之后,针对<strong异步请求数据</strong写的一个案例。注意,本文假设了:<br1.你已经初步了解<codehooks</code的含义了,如果不了解还请移步<ahref"https://reactjs.org/docs/hooksintro.html
Stella981 Stella981
3年前
PHP代码静态分析工具PHPStan
<blockquote最近发现自己写的PHP代码运行结果总跟自己预想的不一样,排查时发现大多是语法错误,在运行之前错误已经种下。可能是自己粗心大意,或者说<codephpl</code检测太简单,不过的确是有一些语法错误埋藏得太深(毕竟PHP是动态语言),那么有没有办法,在代码代码正式运行之前,把语法错误全找出来呢?</blockquote<p
Wesley13 Wesley13
3年前
Java中System.loadLibrary() 的执行过程
_System.loadLibrary()_是我们在使用Java的JNI机制时,会用到的一个非常重要的函数,它的作用即是把实现了我们在Javacode中声明的native方法的那个libraryload进来,或者load其他什么动态连接库。算是处于好奇吧,我们可以看一下这个方法它的实现,即执行流程。(下面分析的那些code,来自于android4.2
Stella981 Stella981
3年前
QeePHP中的访问控制配置
(1)\_code/myapp.php文件中: /      访问被拒绝时的错误处理函数     /    protected function _on_access_denied()    {        $message  "";        require(_MYAP
Stella981 Stella981
3年前
JavaScript中call()与apply()有什么区别?
今天读《JavaScript权威指南》时发现其中有段代码用到了apply方法用于递归实现数组的展开。可是我不懂这个函数的用法,因此查了一下,将资料整理如下。Javascript的每个Function对象中有一个apply方法:function.apply(thisObj,argArray)还有一个类似功能的call方法: