前端js中this指向及改变this指向的方法

本是古典 何须时尚 2024-04-17 06:05 174阅读 0赞

一、 this

this是JS中的关键字, 它始终指向了一个对象, this是一个指针;

参考博文:

this指向及改变this指向的方法

二、 this显示绑定和隐式绑定

  1. this显示绑定

 含义: 当一个函数没有明确的调用对象的时候, 也就是单纯作为独立函数调用的时候, 将对函数的this使用默认绑定: 绑定到全局的window对象

 在显式绑定下: 函数将取得在“ 包含对象“ 里的永久居住权, 一直都会” 住在这里“

在这里插入图片描述

1.1 全局函数

  1. function fire() {
  2. console.log(this === window); //fire此时是全局的方法,this指向window
  3. }
  4. fire(); // 输出true

1.2 函数内嵌套函数

  1. function fire() {
  2. // 我是被定义在函数内部的函数哦!
  3. function innerFire() {
  4. console.log(this === window); //未明确调用对象,this指向window
  5. }
  6. innerFire(); // 独立函数调用
  7. }
  8. fire(); // 输出true
  9. innerFire();

示例:

  1. var a = 1;
  2. console.log(this.a); //1 因为此时this指向了window,因而调用1
  3. function fire() {
  4. var a = 2;
  5. console.log(this.a); //1 因为此时this指向了window,因而调用1
  6. function innerFire() {
  7. var a = 3;
  8. console.log(this.a); //1 因为此时this指向了window,因而调用1
  9. }
  10. innerFire();
  11. }
  12. fire(); //输出1

与作用域的区别: 全局作用域和局部作用域, 去掉this可发现区别

  1. var a = 1;
  2. console.log(a); //1 a在全局作用域
  3. function fire() {
  4. var a = 2;
  5. console.log(a); // 2 fire函数作用域
  6. function innerFire() {
  7. var a = 3;
  8. console.log(a); //3 此时打印输出a,a在innerFIre作用域。从自身作用域查找变量,未找到才网上查找
  9. }
  10. innerFire();
  11. }
  12. fire();

1.3 对象内层函数内部函数

  1. var obj = {
  2. fire: function () { //此时的fire函数其实用到了隐式绑定
  3. function innerFire() {
  4. console.log(this === window); //未明确调用对象,this指向window
  5. }
  6. innerFire();
  7. }
  8. }
  9. obj.fire(); //输出 true

示例:

  1. var a = 1;
  2. console.log(this.a); //1 this指向全局变量window
  3. var obj = {
  4. a: 2,
  5. fire: function () {
  6. var a = 3;
  7. console.log(this.a); //2 因为是obj.fire(),调用了fire函数,因为this指向了obj,输出了obj下的a=2
  8. function innerFire() {
  9. var a = 4;
  10. console.log(this.a); //1 未明确调用对象,this指向window
  11. }
  12. innerFire(); //没有明确调用的对象
  13. console.log(this.a); //2 this指向obj
  14. }
  15. }
  16. obj.fire();

2、 this隐式绑定

a.隐式绑定

 当函数被一个对象“ 包含” 的时候, 我们称函数的this被隐式绑定到这个对象里面, 这时候, 通过this可以直接访问所绑定的对象里面的其他属性, 比如下面的a属性

 在隐式绑定下: 函数和只是暂时住在“ 包含对象“ 的旅馆里面, 可能过几天就又到另一家旅馆住了

在这里插入图片描述

  1. var obj = {
  2. a: 1,
  3. fire: function () { //此时函数的this被隐式绑定到了对象obj
  4. console.log(this == obj); // obj中有fire函数,因而默认this指向obj
  5. console.log(this.a); // 1 this.a 相当于obj.a =1
  6. }
  7. }
  8. obj.fire(); // 输出1

 相同的方法:
 fire函数并不会因为它被定义在obj对象的内部和外部而有任何区别,

  1. function fire() {
  2. console.log(this.a)
  3. }
  4. var obj = {
  5. a: 1,
  6. fire: fire
  7. }
  8. obj.fire(); // 输出1

b.动态绑定:
 this实在代码运行期绑定而不是在书写期

  1. var obj = {
  2. a: 1, // a是定义在对象obj中的属性 1
  3. fire: function () {
  4. console.log(this.a)
  5. }
  6. }
  7. var a = 2; // a是定义在全局环境中的变量 2
  8. obj.fire(); //1 此时fire的指向时obj
  9. var fireInGrobal = obj.fire; //因为fireInGrobal是全局变量,this对于obj的绑定丢失,绑定到了全局window
  10. fireInGrobal(); // 输出 2 输出全局变量啊
  11. var a = 2;
  12. var obj = {
  13. a: 1, // a是定义在对象obj中的属性
  14. fire: function () {
  15. console.log(this.a)
  16. }
  17. }
  18. function otherFire(fn) { //全局函数,this绑定window
  19. fn();
  20. }
  21. otherFire(obj.fire); // 输出2 this对于obj的绑定丢失,绑定到了全局this上面
  22. var obj = {
  23. a: 1,
  24. obj2: {
  25. a: 2,
  26. obj3: {
  27. a: 3,
  28. getA: function () { //obj3.getA() this绑定到了obj3当中
  29. console.log(this.a)
  30. }
  31. }
  32. }
  33. }
  34. obj.obj2.obj3.getA(); // 输出3

三、 this指向

 this的指向不是由定义this决定的, 而是随脚本解析自动赋值的。

1. 全局环境作用域: this在全局环境始终指向window

 变量形式

  1. console.log(this === window) // true
  2. console.log(window.alert === this.alert) // true
  3. console.log(this.parseInt("021", 10)) // 21
  4. var fruit = "banana"; // 定义一个全局变量,等同于window.fruit = "banana"

2. 函数环境 作用域: 函数由谁调用, this就指向谁

2.1 非严格模式

  1. function fn() {
  2. console.log(this); //window
  3. }
  4. fn() === window; // true;window.fn(),此处默认省略window

2.2 严格模式

  a 全局环境下, this指向window

  1. "use strict";
  2. this.b = "MDN";
  3. console.log(this == window) // "MDN"
  4. console.log(b) // "MDN"

 b 函数环境下, this为undefined

  1. function fn() {
  2. "use strict"; // 这里是严格模式
  3. console.log(this); //window
  4. }
  5. fn() === undefined //true

3 对象中的方法函数调用: 指向 该方法所属的对象
 隐式调用

  1. var obj = {
  2. a: 1,
  3. fn: function () {
  4. return this;
  5. }
  6. }
  7. console.log(obj.fn() == obj); //true 函数被obj调用,指向obj

 this动态绑定

  1. var obj = {
  2. a: 1,
  3. fn: function () {
  4. return this;
  5. }
  6. }
  7. console.log(obj.fn()); //1 函数被obj调用,指向obj,输出obj的a=1
  8. var a = 2;
  9. var newfun = obj.fn; //此时更改this指向为全局变量newfun
  10. newfun(); //2 ,this访问全局变量a=2

4 在构造函数中: this始终指向新对象

在这里插入图片描述

  1. function Person(age, name) {
  2. this.age = age;
  3. this.name = name
  4. console.log(this) // 此处 this 分别指向 Person 的实例对象 p1 p2
  5. }
  6. var p1 = new Person(18, 'zs')
  7. var p2 = new Person(18, 'ww')

在这里插入图片描述

5 通过事件绑定的方法: this 指向 绑定事件的对象

  1. oBtn.onclick = function () {
  2. console.log(this); // btn
  3. }
  4. <
  5. button id = "btn" > hh < /button>

6 定时器函数: 因为是异步操作, this 指向 window

 延时函数内部的回调函数的this指向全局对象window( 当然我们可以通过bind方法改变其内部函数的this指向)

 我们常见的window属性和方法有alter, document, parseInt, setTimeout, setInterval, location等等, 这些在默认的情况下是省略了window前缀的。( window.alter = alter)。

6.1 普通定时器

  1. setInterval(function () {
  2. console.log(this); // window
  3. }, 1000);

在这里插入图片描述

6.2 定时器嵌套

  1. function Person() {
  2. this.age = 0;
  3. setTimeout(function () {
  4. console.log(this);
  5. }, 3000);
  6. }
  7. var p = new Person(); //3秒后返回 window 对象

6.3 可以改变this指向 - 想见三方法

  1. function Person() {
  2. this.age = 0;
  3. setTimeout((function () {
  4. console.log(this);
  5. }).bind(this), 3000);
  6. }
  7. var p = new Person(); //3秒后返回构造函数新生成的对象 Person{...}

7 自执行函数(匿名函数): 指向全局变量window

  1. (function inner() {
  2. console.log(this); //this ==> window
  3. })();

8 箭头函数

要点:

  1. a. 箭头函数的this是在定义函数时绑定的, 不是在执行过程中绑定的
  2. b. 箭头函数中的this始终指向父级对象
  3. c. 所有 call() / apply() / bind() 方法对于箭头函数来说只是传入参数, 对它的 this 毫无影响。
  4. var obj = {
  5. a: 1,
  6. fn: () => {
  7. //箭头函数中的this始终指向定义时的环境
  8. //箭头函数中的this始终指向父级对象
  9. console.log(this); //对象内的this调用时一般指向obj,而箭头函数在创建时就指向了obj的父级对象window
  10. }
  11. }
  12. obj.fn(); //window

四、 更改this指向

 每个Function构造函数的原型prototype, 都有方法
call(), apply(), bind()

总结: a call(), apply() 在特定作用域调用函数 b bind() 会创建一个函数的实例, this会被绑定到bind() 函数 bing() 绑定this, bind()() 调用函数

  1. call() 方法

    var Person = {

    1. name: "zhangsan",
    2. age: 19

    }

    function aa(x, y) {

    1. console.log(x + "," + y);
    2. console.log(this);
    3. console.log(this.name);

    }

    aa(4, 5); //this指向window—4,5 window 空

    aa.call(Person, 4, 5); //this指向Person—4,5 Person{}对象 zhangsan

在这里插入图片描述

2. apply() 方法

 apply() 与call() 非常相似, 不同之处在于提供参数的方式, apply() 使用参数数组, 而不是参数列表

  1. var Person = {
  2. name: "zhangsan",
  3. age: 19
  4. }
  5. function aa(x, y) {
  6. console.log(x + "," + y);
  7. console.log(this);
  8. console.log(this.name);
  9. }
  10. aa.apply(Person, [4, 5]); //this指向Person--4,5 Person{}对象 zhangsan

在这里插入图片描述

3. bind() 方法
 bind() 创建的是一个新的函数( 称为绑定函数), 与被调用函数有相同的函数体, 当目标函数被调用时this的值绑定到 bind() 的第一个参数上

在这里插入图片描述

  1. var Person = {
  2. name: "zhangsan",
  3. age: 19
  4. }
  5. function aa(x, y) {
  6. console.log(x + "," + y);
  7. console.log(this);
  8. console.log(this.name);
  9. }
  10. aa.bind(Person, 4, 5); //只是更改了this指向,没有输出
  11. aa.bind(Person, 4, 5)(); //this指向Person--4,5 Person{}对象 zhangsan

在这里插入图片描述

  1. 存储this指向到变量中

    var oDiv1 = document.getElementById(“div1”);
    oDiv1.onclick = function () {

    1. var _this = this; //将this储存在变量中,而且不改变定时器的指向
    2. setTimeout(function () {
    3. console.log(_this); //注意这里是_this,而不是this-- <div id="div1">点击</div>
    4. console.log(this); //定时器的指向没有被改变--仍然是window
    5. }, 1000)

    }

在这里插入图片描述

在这里插入图片描述

2、 更改this指向 - bing, call, apply
 在定时器外, 在绑定事件中的this肯定指向绑定事件的对象div啊, 用call和apply都行

  1. var oDiv1 = document.getElementById("div1");
  2. oDiv1.onclick = function () {
  3. setTimeout(function () {
  4. console.log(this); // 更改this指向为 <div id="div1">点击</div>
  5. }.bind(this), 1000)
  6. }

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,174人围观)

还没有评论,来说两句吧...

相关阅读