this指向哪?

谁调用就指向谁

this 指向哪?先记住一句话:谁调用就指向谁,记住这句话就成功一大半了。

js 复制代码
var userName = '张三'
function fn() {
    var userName = '李四'
    console.log(this.userName) // 张三
}
fn()

函数fn相当于挂在window,调用fn()等同于window.fn(),所以fn可以看做是被window调用,此时this便指向window,所以输出结果是函数外的userName变量。

再看下面的示例:

js 复制代码
var userName = '张三'
var obj = {
    userName: '李四',
    fn: function() {
        console.log(this.userName) // 李四
    }
}

obj.fn()

函数fn被定义在对象obj里,通过obj.fn()调用,回到我们开头的那句话:谁调用就指向谁fnobj调用,所以this指向obj,输出结果是李四。

如果使用windowd.obj.fn()调用呢?结果还是一样的,因为最终是obj调用,所以this指向的还是obj

接着往下看下面这段代码:

js 复制代码
var userName = '张三'
var obj = {
    userName: '李四',
    fn: function() {
        console.log(this.name) // 张三
    }
}

var func = obj.fn
func()

输出结果为张三,因为代码中只是将obj.fn赋值给func,此时函数fn还没有被调用,真正调用是在func()func挂在window下,所以最终相当于是window调用了函数fn,所以this指向的是window

还是应了那句话:谁调用就指向谁

其他情况

1、作为一个函数被直接调用

当函数被直接调用,没有挂在任何对象上时,this指向window

js 复制代码
var userName = '张三'
var obj = {
    userName: '李四',
    fn: function() {
        function a() {
            console.log(this.userName) // 张三
        }
        a()
    }
}
obj.fn()

这里在fn中定义了一个函数a并调用,注意这里函数a只是在函数fn内,它并没有挂在哪个对象上,也没有通过其他方式被调用,而是作为一个函数被直接调用,所以this指向window

2、箭头函数

箭头函数的特点是没有自己的this也不能通过new调用。箭头函数通过作用域向上查找,找到离包裹它最近的那一个普通函数的this作为自己的this,如果没有则指向全局对象window

js 复制代码
var userName = '张三'
var obj = {
    userName: '李四',
    fn: function() {
        var func = () => {
            console.log(this.userName) // 李四
        }
        func()
    },
    a: {
        b: () => {
            console.log(this.userName) // 张三
        }
    }
}
obj.fn()
obj.a.b()

func是一个箭头函数,箭头函数通过向上查找找到fnfnthis指向obj,所以箭头函数的this指向的也是obj,输出结果:李四。

obj.a.b()则指向window,输出结果:张三。

3、new 构造函数

当函数通过使用new调用时,new过程中会创建一个新的对象,而this便是指向这个新创建的对象。

js 复制代码
function fn(name) {
    this.userName = name
    this.age = 18
    console.log(this) // {userName: '张三', age: 18}
}
let data = new fn('张三')
// new的同时内部会默认把this做回返回值返回
console.log('data: ', data) // data: {userName: '张三', age: 18}

如何改变this指向

1、call、apply、bind

可以通过callapplybind的第一个参数传值作为this值,改变this指向。

js 复制代码
obj.fn('hello') // hello,张三
obj.fn.call({ userName: '李四' }, 'hello') // hello,李四
obj.fn.apply({ userName: '王五' }, ['hello']) // hello,王五
obj.fn.bind({ userName: '老六' }, 'hello')() // hello,老六

2、call、apply、bind区别

从上面的使用可以看到,这三个API的参数形式除了第一个参数外是有一些区别的

  • callbind是多参数的形式:call(thisArg, arg1, arg2...)
  • apply是数组的形式:call(thisArg, [arg1, arg2...])

另外一个区别是:bind的返回值是一个函数,需要自己再手动调用一次,而callapply则不用。

相关推荐
千寻girling29 分钟前
《 MongoDB 教程 》—— 不可多得的 MongoDB
前端·后端·面试
掘金安东尼35 分钟前
⏰前端周刊第 452 期(2026年2月2日-2月8日)
前端·javascript·github
ArkPppp40 分钟前
NestJS全栈实战笔记:优雅处理 Entity 与 DTO 的映射与字段过滤
javascript·nestjs
钟智强1 小时前
React2Shell:CVE-2025-66478 Next.js 远程执行漏洞深度分析与代码剖析
开发语言·javascript·ecmascript
Dragon Wu1 小时前
Electron Forge集成React Typescript完整步骤
前端·javascript·react.js·typescript·electron·reactjs
华仔啊1 小时前
jQuery 4.0 发布,IE 终于被放弃了
前端·javascript
空白诗1 小时前
高级进阶 React Native 鸿蒙跨平台开发:slider 滑块组件 - 进度条与评分系统
javascript·react native·react.js
晓得迷路了2 小时前
栗子前端技术周刊第 116 期 - 2025 JS 状态调查结果、Babel 7.29.0、Vue Router 5...
前端·javascript·vue.js
How_doyou_do2 小时前
执行上下文、作用域、闭包 patch
javascript
唐梓航-求职中2 小时前
编程大师-技术-算法-leetcode-355. 设计推特
算法·leetcode·面试