写点什么

重学 JS | 改变函数上下文的 3 种方式

用户头像
梁龙先森
关注
发布于: 2021 年 01 月 11 日
重学JS | 改变函数上下文的3种方式

在重学 JS 系列文章中,上一节学习了 JS 中的 this 指向问题。这节学习如何改变函数的上下文,实际上是改变函数体中 this 的指向。call()函数和apply()函数是为改变函数运行时上下文而存在的,但它们并不是从函数继承而来。bind()函数也能达到这个目的。下面看看三者的用法:

1. call()函数的用法

call()函数调用一个函数时,会将该函数的执行上下文改变为另一个对象。语法如下:

// Function : 调用的函数// context : 新的对象上下文,函数中的this指向context,若context为null|undefined,则执行window// arg1,arg2 : 参数列表  Function.call(context,arg1,arg2,...)       
复制代码

看个简单例子:

function add(x,y){	return this.x+this.y}var obj = {	x:10,  y:20}add.call(obj) // 30
复制代码

例子里的add()函数执行时,this指向了 obj。可以粗俗的理解为add()函数挂载到 obj 对象上,执行完函数后,obj 对象再删除了add()函数属性。下面通过代码模拟下这个过程:

Function.prototype.customeCall = function(cxt){  // 不传context,或者null|undefined,默认指向window	let context = cxt || window    // 将调用函数挂载到当前context  context.fun = this  // 获取除了context外的参数  const args = Array.from(arguments).splice(1)  // 执行调用函数  const result = context.fun(...args)  // 执行完后删除属性  delete context.fun  return result}// 按照例子执行add.customeCall(obj) // 30
复制代码
2. apply()函数的用法

apply()作用与call()函数是一致的,只是在传参形式上不同。

// [argArray] 这里传递的是数组Function.apply(context,[argArray])
复制代码

简单例子:

function add(x,y){	return x + y}function mAdd(x,y){  // 注意apply的传参为数组,与call()函数不一致	return add.apply(this,[x,y]) }mAdd(10,20) // 30
复制代码

模拟下实现:

Function.prototype.customeApply = function(ctx,argArray){	let context = ctx || window  context.fun = this  if(!Array.isArray(argArray)){  	throw new Error('参数必须为数组')  }  if(!argArray){  	return context.fun()  }  const result = context.fun(...argArray)  delete context.fun  return result}
复制代码
3. bind()函数的使用

bind()函数创建一个新函数,在调用时设置 this 关键字为提供的值,在执行新函数时,将给定的参数列表作为原函数的参数序列,从前往后匹配。语法如下:

Function.bind(context,arg1,arg2,...)
复制代码

简单例子:

function add(x,y){	return this.x+this.y}var obj = {	x:10,  y:20}// 函数上下文指向obj返回新函数var newFun = add.bind(obj) newFun() // 30
复制代码

模拟下实现:

Function.prototype.customeBind = function(context, ...rest) {  if (typeof this !== 'function')     throw new TypeError('invalid invoked!');  var self = this;  return function F(...args) {    if (this instanceof F) {      return new self(...rest, ...args)    }    return self.apply(context, rest.concat(args))  }}
复制代码
4. 总结

call()函数、apply()函数、bind()函数三者都会改变函数调用时的执行主体,修改this的指向。

call()函数、apply()两个函数是立即执行返回,而bind()函数是返回一个新函数,在任何使用可以调用。

apply()函数第二个入参为数组,与其他 2 个函数不一致。


发布于: 2021 年 01 月 11 日阅读数: 20
用户头像

梁龙先森

关注

脚踏V8引擎的无情写作机器 2018.03.17 加入

还未添加个人简介

评论

发布
暂无评论
重学JS | 改变函数上下文的3种方式