Skip to main content

JS 全局环境和对象调用中的 this 指向?

· 3 min read

this 指向在函数定义时不确定,调用时才确定。

  1. 全局环境:浏览器 this === window,Node 中 this === global,严格模式为 undefined
  2. 对象方法obj.method() 中 this 指向点号左侧的对象
  3. 独立调用:函数脱离对象后丢失绑定,this 回退到全局(严格模式 undefined)
  4. 箭头函数:没有独立的 this,捕获定义时所在作用域的 this
  5. 显式绑定call/apply/bind 可手动指定任意 this

核心原则:只看如何调用,不看在哪定义。


this 的规则其实不复杂,复杂的是总有人想用直觉去理解它。记住一条:this 在函数定义时不确定,调用时才确定

全局环境

浏览器顶层代码里 this === window,Node.js 里 this === global。ES2020 搞了个 globalThis 统一收口,省得你判断环境。

console.log(globalThis === window); // true(浏览器)
console.log(globalThis === global); // true(Node)

严格模式更干脆——全局 this 直接给 undefined,逼你写出更安全的代码。

JS 全局环境中的 this 指向

对象方法调用

obj.fn() 叫隐式绑定。this 指向点号左边的东西,没有例外。

const user = {
name: 'Kimi',
greet() {
console.log(this.name);
}
};

user.greet(); // 'Kimi'

换种写法,结果完全不同:

const fn = user.greet;
fn(); // undefined —— this 丢了

函数不"属于"某个对象,它只是被借过去调用了。一旦脱离对象单独执行,this 就变回全局对象。这叫隐式丢失,面试常问。

多层嵌套

const user = {
name: 'Kimi',
profile: {
name: 'Profile',
get() {
return this.name;
}
}
};

user.profile.get(); // 'Profile'

this 只看直接调用者——点号左边最近的那个。user.profile.get() 里,get 的调用者是 profile,不是 user

JS 对象方法调用中的 this 指向

常见坑

赋值即丢失

const obj = {
name: 'test',
fn() {
console.log(this.name);
}
};

const fn = obj.fn;
fn(); // undefined

把方法存到变量里,调用方式从 obj.fn() 变成 fn(),this 就没了。

回调传递

const btn = {
text: 'Click me',
onClick() {
console.log(this.text);
}
};

setTimeout(btn.onClick, 100); // undefined

这里传的是函数引用,不是调用。btn.onClick 取到的是函数本身,上下文丢得一干二净。

怎么修

箭头函数

箭头函数没有自己的 this,它继承定义时所在作用域的 this。最适合做回调:

const obj = {
name: 'timer',
start() {
setTimeout(() => {
console.log(this.name); // 'timer'
}, 100);
}
};

start 里的箭头函数捕获了 start 的 this,所以 setTimeout 回调里还能拿到 name

箭头函数只适合做回调。别在对象方法上用箭头函数定义——那拿不到对象本身。

call / apply / bind

种显式指定 this 的方式:

function log() {
console.log(this.name);
}

const obj = { name: '手动指定' };

log.call(obj); // '手动指定'
log.apply(obj); // '手动指定'
const bound = log.bind(obj);
bound(); // '手动指定'

callapply 区别只有一个:传参方式(逐个 vs 数组)。bind 返回新函数,this 永久绑定。

一句话

别问"这个函数里 this 是什么"——问它是怎么被调用的

调用方式this 指向
全局直接调用全局对象(严格模式 undefined)
obj.method()点号左侧的对象
独立调用 fn()全局对象(严格模式 undefined)
箭头函数定义时的外部作用域
call/bind/apply手动指定的对象