javascript修改_修改JavaScript中的this指向

cb74d0c505b5bc4c6c3db673c37b597c.png

浅谈函数上下文调用模式

修改JavaScript中的this指向就是本期的重点。要实现这个需求,就要使用函数上下文调用模式,接下来就和大家共同探讨下函数上下文调用模式 -- call、apply、bind

一、我们先从语法上了解下这三种方法。

1.1: call();

语法:函数名.call(期望函数内部this指向谁, 参数1,参数2....);

9b36653500e639e35e3788b7424dbd47.png

第14行普通方式调用getSum()函数,this指向window;

第15行用call()的方式调用getSum()函数, 第1个参数传入”期望getSum函数中的this指向”,后面的参数依次传入getSum函数的参数即可。此时getSum函数一样被执行,不同的是getSum函数中的this就指向了obj对象,同时也把100,200分别赋值给形参a和b. 执行结果如下:

4792d6c21dd7e634d47b7e1d0c6050ec.png

这样我们就轻松实现了修改函数内部this指向.

1.2:apply();

语法:函数名.apply(this的新指向 , 数组或者伪数组);

注意apply()和call()的区别在于apply()只有2个参数,第一个参数是this的新指向,第二个参数是数组或者伪数组,调用的时候会把第二个参数(数组或伪数组)的元素依次的赋值给被调用函数的形参。

ecaf784fbd1f2e517f7fdcc8d469f129.png

第24行普通方式调用getSum()函数,this指向window;

第25行用apply()的方式调用getSum()函数,此时getSum()函数中的this就指向了obj对象,同时把数组的元素100,200,300依次赋值给getSum()函数的形参a,b,c ; 执行结果如下:

ae7c19a78fa400aa92649d338b3c3610.png

1.3:bind();

语法:函数名.bind( this的新指向 ,可以写参数也可以不写参数 );

需要注意的是函数用bind()的方式调用并不会执行该函数,而是会返回一个函数体一模一样但是修改了this指向后的函数。

db3575e799bc3992e1e5c158e59f394f.png

第34行普通方式调用getSum()函数,this指向window;

第36行虽然用bind()的方式调用getSum()函数,但是此时并不会执行getSum()函数,而是会返回一个和getSum()函数的函数体一模一样但是this已经修改成obj对象的函数了,这个函数被fn变量接收。 执行结果如下:(只有一次函数体被执行,就是34行的调用)。

302e8206d1b8f6d80f298931f7c284a8.png

此时如果调用fn()函数,就相当于执行getSum()函数,但是getSum函数中的this已经被修改成了obj对象,调用代码和执行结果如下:

915da9f3bcb26f1318732f02bcef10e9.png

ce4a3566b703f71218657df883641487.png

前面介绍bind()的语法说除了this的新指向,参数可以写也可以不写,所以36行38行代码也可以写成如下这样:

27e73d0c07554da20a61a7fdfbee8786.png

执行结果一样,如下:

e0d50fb0b749a07d0a08fe233436124b.png

二、上下文调用模式注意细节:

2.1 大家都知道javascript中的函数(普通函数、构造函数)本质上是一个对象,是由Function()构造函数实例化出来的对象,而call、apply、bind这三个方法都是定义在Function.prototype原型中的,那么意味着javascript中的所有函数都可以点出这三个方法来。

c5598583a46748f2da98aa8745151c34.png

2.2 如果使用函数上下文模式调用函数,第一个参数不是指向一个对象,而是指向一个基本数据类型的值,那么函数中this的指向又该指向谁呢?代码如下:

ded25c4f2a1cffd2c12ffc3eb8513754.png

52行53行54行,他们使用call()的方式调用foo()函数,this分别指向Number包装类型对象、String包装类型对象和Boolean包装类型对象;

55行,56行,57行,58行都指向window对象。 执行结果如下: (当然前提是非严格模式下,严格模式下修改this为null或者undefined都不允许指向window,关于严格模式另起篇章再究)。

39ecf5cd98d545d92a43c0e6c3366097.png

2.3 哪个函数使用上下文模式调用,修改的this就是哪个函数的,代码如下:

355d1a98da326fe36a0af5ee661f6896.png

上述这道题不要以为第73行testOne函数被上下文模式调用,所以在testOne函数的函数体中调用testTwo函数,他的this也指向obj对象,不是的。哪个函数被上下文模式调用,那哪个函数的this才会发生改变。

testOne函数被上下文模式调用,所以testOne函数的this指向obj对象; 而在testOne函数的函数体中第67行调用testTwo函数还是普通调用,所以testTwo函数的this还是window对象。执行结果如下:

a2437384043f2554a455327feb6be432.png
  1. 函数上下文调用模式的使用场景究竟

3.1 元素都是整数的数组求最大值。

ed1712be64a55376b79c796a579b1f82.png

如果要求出一个整数数组中的最大值,传统的做法是遍历数组,元素两两比较,最后得到最大值,但是这样较繁琐,所以我们联想到js中的Math对象提供的max()方法可以求一堆数中的最大值,所以我们就用apply的方式调用max()方法,不修改它this的指向,只是利用apply()方法的语法特点把arr数组的元素依次的交给Max()方法,这样就能得到arr数组中的最大值。执行结果如下:

64158d7dd7a9878df3191878edd704c5.png

3.2 伪数组转换成真数组

a18b60719bd981a16442ebbe2a1610f0.png

原始的做法需要遍历这个伪数组weiArr,然后把元素一个一个的往声明的真数组arr中添加,需要用到遍历所以较复杂。执行结果如下:

5be3657c49bd4c5efa7c4ed1293395d6.png

用函数上下文调用模式来处理该问题就较容易:

68940fa395234a8219fc421cc26a411c.png

做法1利用apply()方法的特性把weiArr这个伪数组中的元素依次的交给push方法,减去了遍历这个伪数组步骤。执行结果如下:

b122562a695837e50f04b5f26a99f881.png

c5f07c8953d83a2b689a78627b0172b5.png

做法2使用call的方式调用slice方法,修改slice方法中的this为weiArr这个伪数组, 大家在上一篇this的指向中都知道谁调用方法,方法中的this就是谁, 那现在slice方法中的this被修改成了weiArr这个伪数组,那给人的感觉就是weiArr这个伪数组在调用这个方法。(有同学可能会问那为什么weiArr不直接调用slice方法呢?原因是因为他是伪数组,不能直接点出数组的方法来。) 而slice这个方法就是用来做截取的,题中只给一个参数0,意味着从第0个元素开始截取一直到末尾。 所以arr2就是一个拥有和伪数组相同元素的真数组。 执行结果如下:

ce48bfaac692c321ea6e69aa2b59ec66.png

5b3efaccf4342130e0ba59302474664f.png

做法3利用的是数组的concat方法,concat方法允许数组arr3连接一个个的数值作为他的新元素,所以这里用apply的方式调用concat,就是为了把weiArr这个伪数组里面的元素一个个的交给concat函数。执行结果如下:

9fcde603b67b3875db9377ff0d6d2990.png

3.3 借用构造函数继承。

b9965e2fad55a20a5f5527d95d61fa8f.png

在Student构造函数里面,121行(注释)、122行(注释)、123行都可以借用Person构造函数中的赋值代码给自己实例化出来的对象赋值。 执行结果如下:

e020db590087e7b5d80ccf0b4b3e5efa.png

3.4 检测数据类型。

45c59322b9f3b70a698e228451bbfefc.png

这里都是在借用Object.prototype原型中的toString方法,而这个toString方法明确规定了返回的结果是:”[object type]”,其中type是数据的类型。所以用这种方式可以检测所有数据的数据类型。 执行结果如下:

d818e124e51a2b020f5a9f41b30e6cea.png

好啦,本期干货就全部交给大家了,大家要不要动动小手自己试一下呢?

下一期预告: 《带你揭开BFC的面纱!》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值