美文网首页
js的this指向问题

js的this指向问题

作者: 扶得一人醉如苏沐晨 | 来源:发表于2023-10-18 19:02 被阅读0次

一、全局环境下的 this(与函数无关--直接访问this)

直接使用this,永远指向window

    <script>
      console.log(this); //window
    </script>

二、函数中的this

2.1、作为普通函数被调用时

this指向调用该函数的对象

  • this指向全局对象window
  • 严格模式下 this是undefined
function fn() {
  console.log(this); //window
}
fn();
//相当于window.fn()


function fn() {
  "use strict";
  console.log(this); //undefined
}
fn();

2.2、作为对象的方法被调用

this指向调用该函数的对象

当函数作为对象方法被调用时this指向该对象

let obj = {
  age: 18,
  fn: function () {
    console.log(this === obj); //true
    console.log(this.age); //18
  },
};
obj.fn()

2.3、作为构造函数被调用时

  • 构造函数里的this指向 new创建的实例对象
构造函数的原理(new之后发生了什么)

官方解释:

  1. 创建一个空的简单JavaScript对象(即{});
  2. 为步骤1新创建的对象添加属性__proto__,将该属性链接至构造函数的原型对象 ;
  3. 将步骤1新创建的对象作为this的上下文 ;
  4. 如果该函数没有返回对象,则返回this

咱们的总结:

1、自从用new调用函数后,JS引擎就会在内存中创建一个空对象{}const newObj = {};
2、将新对象newObj的__proto__属性链接至构造函数的原型对象 newObj.__proto__ = FunctionName.prototype
3、构造函数内部的 this 被赋值为这个新对象(即 this 指向新对象)this = newObj
4、执行构造函数内部代码;
5、如果该函数没有返回对象,则默认返回this。

构造函数中的this指向,指向构造出来的实例对象

eg

image.png

2.4、定时器函数里面的this

//this指向window 实际上为window.setTimeout(),也是指向函数的调用者
setTimeout(function () {
  console.log("定时器的this" + this); //window
}, 1000);

定时器函数的调用,实际上是window.setTimeout(),因此定时器函数的this指向window

2. 5、立即执行函数里面的this

//6.立即执行函数  this指向window  相当于普通函数,只是不需要手动调用
(function () {
    console.log('立即执行函数的this' + this); //window
})();

2.6、绑定事件函数里面的this

this指向调用该函数的对象

//4.绑定事件函数
let btn = document.querySelector("button");
btn.onclick = function () {
  console.log("绑定事件的this" + this); // 指向btn 也是指向函数的调用者
};

绑定事件的函数,同样遵循谁调用,this指向谁的原则,在这里是btn绑定了点击事件,因此这里的this指向函数的调用者btn

2.7、箭头函数里面的this

  • 在js中有全局作用域,函数作用域,块级作用域,没有对象作用域
  • 箭头函数里面没有自己的this,箭头函数的this跟箭头函数所在作用域里面的this一致

2.7.1、箭头函数定义在函数中

<script>
    function fn() {
        return () => {
            console.log(this);
        }
    }
    let test = fn()
    test()//window
</script>

箭头函数定义在fn函数作用域内,则箭头函数的this与所在作用域的this指向一致,而普通函数的this指向全局window对象,则该箭头函数也指向window

2.7.2、箭头函数定义在对象中

<script>
    let obj = {
        name: 'cirrod',
        play: () => {
            console.log(this);
        }
    }
    console.log(obj.play()); //window全局对象
</script>

play箭头函数定义在对象中,而在js中只有全局作用域,函数作用域,块级作用域,没有对象作用域,所以相当于箭头函数定义在全局作用域中,箭头函数的this与所在作用域的this指向一致,所以this指向全局对象window

2.7.3、箭头函数定义在对象的方法中

<script>
let obj = {
    name: 'cirrod',
    fn: function() {
        return {
            play: () => {
                console.log(this);
            }
        }
    }
}
let obj1 = obj.fn();
console.log(obj1.play());//obj这个对象
</script>

箭头函数定义在fn函数的返回对象中,而对象没有作用域,则向上一层查找fn函数,相当于箭头函数定义在fn函数的作用域内,fn函数的this指向自己所属的对象obj,箭头函数的this与所在作用域的this指向一致,所以箭头函数的this指向为obj

2.7.4、箭头函数定义在定时器中

2.7.4.1、定时器在全局作用域中

<script>
    setTimeout(() => {
        console.log(this); // window
    }, 100)
</script>

箭头函数定义在定时器的参数上,定时器的参数没有作用域,向外一级是全局作用域,相当于箭头函数定义在全局作用域,箭头函数的this与所在作用域的this指向一致,所以箭头函数的this指向为window

2.7.4.2、定时器在函数作用域

<script>
    function Person(name) {
        this.name = name
        setTimeout(() => {
            console.log(this); // cirrod这个实例对象
        }, 100)
    }
    const cirrod = new Person('杨某某')
</script>

箭头函数定义在定时器的参数上,定时器的参数没有作用域,向外一级是构造函数的作用域,相当于箭头函数定义在构造函数的作用域,而构造函数的this指向实例对象,箭头函数的this与所在作用域的this指向一致,所以箭头函数的this指向为构造函数的实例对象cirrod

三、总结

image.png

四、如何更改this指向

call,apply和bind方法都可以用来更改this指向
区别
  • call、apply与bind都用于改变 this 绑定
  • call、apply 在改变 this 指向的同时还会执行函数,一次性的。
    不同的是 call方法传递函数调用形参是以散列形式,而 apply 方法的形参是一个数组。在传参的情况下,call的性能要高于 apply,因为 apply 在执行时还要多一步解析数组。
  • bind 在改变 this 后是返回一个全新的绑定函数,即返回一个新的函数,不直接执行函数。并且此后 this 的指向无法再次通过 call、apply、bind 改变。

4.1、call

使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数

function.call(thisArg, arg1, arg2, ...)

[thisArg] 在 func 函数运行时使用的 this 值。请注意,this 可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 nullundefined 时会自动替换为指向全局对象,原始值会被包装

[arg1, arg2, ...] 参数列表

例子

let objCall = {
  name: "我是 Call",
};
function fn() {
  console.log("参数 => ", ...arguments);
  console.log("name => ", this.name);
}
fn.call(objCall, 1, 2, 3);
// 参数 =>  1 2 3
// name =>  我是Call

4.2、apply

调用一个具有给定 this 值的函数,以及以一个数组(或类数组对象)的形式提供的参数

func.apply(thisArg, [argsArray])
[thisArg] 必选的 同 call 一样
[argsArray] 可选的

例子

let objApply = {
  name: "我是 Apply",
};
function fn() {
  console.log("参数 => ", ...arguments);
  console.log("name => ", this.name);
}
fn.apply(objApply, [1, 2, 3]);
// 参数 =>  1 2 3
// name =>  我是 Apply

4.3、bind

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

function.bind(thisArg,arg1,arg2,arg3,....)

例子

let objBind = {
  name: "我是 Bind",
};
let objApply = {
  name: "我是 Apply",
};

function fn() {
  console.log("参数 => ", ...arguments);
  console.log("name => ", this.name);
}
let bfn = fn.bind(objBind, 1, 2, 3);
//需要自己主动执行
bfn();
// 参数 =>  1 2 3
// name =>  我是 Bind

相关文章

  • js:this指向问题

    var 作用域 先来看个简单的例子: 直觉地,内部函数可以访问外部函数的变量,外部不能访问内部函数的变量。上面的例...

  • JS this指向问题

    this:指的是你的函数执行时所在的环境(作用域) 函数this的指向(箭头函数除外): 谁调用函数,这个this...

  • js的this指向问题

    跟函数在哪定义的和在哪执行的都没有关系 1、函数执行看函数名前面有没有".",没有就是window,有的话"."前...

  • js的this指向问题

    this指向详情参考:https://blog.csdn.net/weixin_37722222/article/...

  • JS进阶篇-this指向问题

    JS中this的指向问题不同于其他语言,JS中的this不是指向定义它的位置,而是在哪里调用它就指向哪里。 JS中...

  • JavaScript经典面试题(2)--this指向及应用

    关于js中的this指向问题:有很多同学刚接触js时,对this的指向问题很是迷惑,在有些不常见情况,往往搞不...

  • js之this指向问题

    结果如下。一开始有点迷惑,success不是属于myMessage对象的一个属性吗?为什么this不是指向myMe...

  • js中this指向问题

    this的指向在函数定义的时候是无法确定的,只有函数执行的时候才能确定this到底指向谁,实际this指向是调用他...

  • JS中this指向问题

    首先声明,添加删除线的都是不太确定的 下面我们分情况解释: 1、函数调用模式--当一个函数并非一个对象的属性时,那...

  • JS--this指向问题

    JS--this指向问题 1.function中的this在不同环境下的指向 事件调用环境:谁触发的事件,函数里面...

网友评论

      本文标题:js的this指向问题

      本文链接:https://www.haomeiwen.com/subject/qhnwbdtx.html