• 为什么要改变this指向?


    首先this是什么?

    按照官方正规的解释,this关键字的意义被解释为“指向当前对象的引用”。this是面向对象语言中的一个重要概念,在JAVA,C++等面向对象的语言中,this固定指向运行时的当前对象。但是在JavaScript中,由于JavaScript的动态性(边解释边执行),this的指向在运行时才确定。它代表函数运行时自动生成的一个内部对象,一般在函数内部使用。

    1. this的值通常是由所在函数的执行环境决定,也就是说要看函数是如何被调用的;
    2. 同一个函数每一次调用,this都可能指向不同的对象;

    为什么要改变this指向? 

    bind,call,apply的作用都是用来改变this指向的,那为什么要改变this指向呢?

    1. var position="out";
    2. let obj={
    3. position:"in",
    4. find:function(){
    5. console.log(this.position)
    6. }
    7. };
    8. obj.find(); //in,this指向obj对象
    9. setTimeout(obj.find,0); //out,由于setTime()是异步操作,this指向window对象
    '
    运行

    如程序说展示 find()中的 this 是指向调用它的 obj 对象的,而在定时器 setTimeout 中调用 find(),this 是指向window对象的。但我们需要的是 find()的 this 指向obj对象,因此我们需要修改 this 的指向。

    1.apply方法 

    apply接受两个参数,第一个是this的指向,第二个是函数接受的参数,以数组的形式传入,且当第一个参数为null、undefined的时候,默认指向window(在浏览器中),使用apply方法改变this指向后原函数会立即执行,且此方法只是临时改变thi指向一次。

    eg:求数组中的最大值

    1. var arr=[9,2,5,6];
    2. console.log(Math.max.apply(null, arr)); //返回9
    '
    运行

    其中Math.max函数的参数是以参数列表,如:Math.max(9,2,5,6)的形式传入的,因此我们没法直接把数组当做参数,但是apply方法可以将数组参数转换成列表参数传入,从而直接求数组的最大值。 

    2.call方法

    call方法的第一个参数也是this的指向,后面传入的是一个参数列表。当一个参数为null或undefined的时候,表示指向window,和apply一样,call也只是临时改变一次this指向,并立即执行。

    1. var arr=[9,2,5,6];
    2. console.log(Math.max.call(null,arr[0],arr[1],arr[2],arr[3])); //返回9
    '
    运行

    采纳以参数列表的形式传入,而apply以参数数组的形式传入。 

    3.bind方法

    bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入,call则必须一次性传入所有参数),但是它改变this指向后不会立即执行,而是返回一个永久改变this指向的函数,调用新函数的时候才会执行目标函数。

    面试题:

    手写bind()函数

    1. //实现bind方法
    2. Function.prototype.bind = function(oThis) {
    3. if (typeof this !== 'function') {
    4. // closest thing possible to the ECMAScript 5
    5. // internal IsCallable function
    6. throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable');
    7. }
    8. var aArgs = Array.prototype.slice.call(arguments, 1),
    9. fToBind = this,
    10. fNOP = function() {},
    11. fBound = function() {
    12. // this instanceof fBound === true时,说明返回的fBound被当做new的构造函数调用
    13. return fToBind.apply(this instanceof fBound
    14. ? this
    15. : oThis,
    16. // 获取调用时(fBound)的传参.bind 返回的函数入参往往是这么传递的
    17. aArgs.concat(Array.prototype.slice.call(arguments)));
    18. };
    19. // 维护原型关系
    20. if (this.prototype) {
    21. // 当执行Function.prototype.bind()时, this为Function.prototype
    22. // this.prototype(即Function.prototype.prototype)为undefined
    23. fNOP.prototype = this.prototype;
    24. }
    25. // 下行的代码使fBound.prototype是fNOP的实例,因此
    26. // 返回的fBound若作为new的构造函数,new生成的新对象作为this传入fBound,新对象的__proto__就是fNOP的实例
    27. fBound.prototype = new fNOP();
    28. return fBound;
    29. };
    30. var arr=[1,11,5,8,12];
    31. var max=Math.max.bind(null,arr[0],arr[1],arr[2],arr[3]);
    32. console.log(max(arr[4])); //12
    '
    运行

     

     

  • 相关阅读:
    【2024最新华为OD-C/D卷试题汇总】[支持在线评测] 机器人搬砖(100分) - 三语言AC题解(Python/Java/Cpp)
    ds配置datax数据同步工具
    维格云Q-Linker入门教程
    AcWing 197. 阶乘分解
    如何绘制【逻辑回归】中threshold参数的学习曲线
    京东商品详情API:电商创新的利器
    深度学习入门笔记 —— 循环神经网络 RNN
    如何在Spring Boot框架下实现高效的Excel服务端导入导出?
    jsp+sql毕业生招聘系统免费系统+论文
    SpringBoot 中的 Liquibase 适配达梦数据库(DM)和 Flowable 工作流
  • 原文地址:https://blog.csdn.net/weixin_63050915/article/details/127096691