this指向问题

this主要有以下几个使用场合。
(1)全局环境

全局环境使用this,它指的就是顶层对象window。

javascript 复制代码
this === window // true

function f() {
  console.log(this === window);
}
f() // true

(2)构造函数

构造函数中的this,指的是实例对象

javascript 复制代码
var Obj = function (p) {
  this.p = p;
};

var o = new Obj('Hello World!');
o.p // "Hello World!"

(3)对象的方法

如果对象的方法里面包含this,this的指向就是方法运行时所在的对象。该方法赋值给另一个对象,就会改变this的指向

javascript 复制代码
var A = {
   name: '张三',
   describe: function () {
      console.log('姓名:'+ this.name);
   }
};

var B = {
    name: '李四'
};

var name = '王五';

B.describe = A.describe;
A.describe(); // "姓名:张三"
B.describe(); // "姓名:李四"

var f =  A.describe;
f(); // "姓名:王五"

如果this所在的方法不在对象的第一层,这时this只是指向当前一层的对象,而不会继承更上面的层。

javascript 复制代码
var a = {
  p: 'Hello',
  b: {
    m: function() {
      console.log(this.p);
    }
  }
};

a.b.m() // undefined
// a.b.m方法在a对象的第二层,该方法内部的this不是指向a,而是指向a.b

如果将嵌套对象内部的方法赋值给一个变量,this依然会指向全局对象。

javascript 复制代码
var a = {
  b: {
    m: function() {
      console.log(this.p);
    },
    p: 'Hello'
  }
};

var hello = a.b.m;
hello() // undefined

上面代码中,m是多层对象内部的一个方法。为求简便,将其赋值给hello变量,结果调用时,this指向了顶层对象。为了避免这个问题,可以只将m所在的对象赋值给hello,这样调用时,this的指向就不会变。

javascript 复制代码
var hello = a.b;
hello.m() // Hello

(4)call()、apply()、bind()显性绑定

javascript 复制代码
window.age = 29;
let a = {
    age: 33
};
let b = {
    age: 66
};
function sayAge() {
    console.log(this.age);
}
sayAge();    // 29 this值默认为window对象
sayAge.call(a);    // 33 将this值显性切换为对象a
sayAge.apply(b);     // 66 将this值显性切换为对象b

let sayAgeAgain = sayAge.bind(a);    // 创建新函数sayAgeAgain
sayAgeAgain();    // 33

bind跟call、apply的不同之处在于:它控制函数this值的同时,会创建一个新的函数(准确来说是改变新函数的this值)。

(5)箭头函数

箭头函数没有自己的this对象,内部的this就是定义时上层作用域中的this,箭头函数内部的this是固定的,不可变,而普通函数的this指向是可变的

javascript 复制代码
window.color = 'red';
let obj = {
    color: 'blue'
};
// 此时箭头函数sayColor()声明在全局上下文
let sayColor = () => console.log(this.color);
obj.sayColor = sayColor;

obj.sayColor();     // 依旧为red
sayColor.call(obj); // 依旧为red 


function foo() {
  setTimeout(() => {
    console.log('id:', this.id);
  }, 100);
}
var id = 21;
foo.call({ id: 42 });
// id: 42

由于箭头函数没有自己的this,所以当然也就不能用call()、apply()、bind()这些方法去改变this的指向。

相关推荐
一直奔跑在路上1 分钟前
深入浅出RDMA:原理、应用与实战指南
开发语言·php
IVEN_5 分钟前
本地正常,Docker 怎么就空白:Next.js SSR 的 Alpine musl DNS 陷阱
前端·docker·next.js
凡人叶枫5 分钟前
Effective C++ 条款24:若所有参数皆须要类型转换,请为此采用 non-member 函数
linux·前端·c++·算法·嵌入式开发
用户887665426637 分钟前
Web3 前端实时通信如何落地:从 SSE 订阅到行情、订单与账户状态更新
前端·react.js·web3
j7~10 分钟前
【C++】STL--string类--拆析解剖string类的实现以及string类的底层详解(2)
开发语言·c++·浅拷贝·深拷贝·string类的实现·string拷贝构造·string赋值重载
an3174210 分钟前
使用 LangGraph + DeepSeek 构建 AI 面试官:状态图设计与实践
前端·ai编程
代码不加糖11 分钟前
MessageChannel是什么,有什么使用场景?
前端·javascript
小小龙学IT15 分钟前
HTMX:让 HTML 重新成为前端核心的超轻量动态交互库
前端·html·交互
星栈15 分钟前
写 Makepad Demo 不难,难的是把它写成项目
前端·rust
用户0595401744616 分钟前
localStorage清除策略踩坑实录:一个过期的token让我排查了3小时
前端·css