真的!真的就一句话就能明白this指向问题

就一句话:函数也是对象

为什么这个认知能帮我们理解this指向问题?且由我来为客官们解读。

第一部分:函数作为对象的本质

函数是特殊的对象

既然函数是对象 ,那么函数也就有属性方法

代码示例:

javascript 复制代码
// 函数是对象,有属性和方法
function myFunction() {
    console.log("Hello");
}

// 函数对象的属性
console.log(myFunction.name);        // "myFunction"
console.log(myFunction.length);      // 0 (参数个数)
console.log(myFunction.prototype);   // 原型对象
console.log(typeof myFunction);      // "function"

那么就知道函数的属性可以存储数据与函数的方法可以控制函数的行为。

函数对象的特殊方法

函数对象的原型链上有callapplybind等方法,这些方法能控制函数执行时的this 指向,说明了this的指向是可以被控制的。

代码示例:

javascript 复制代码
function test() {
    console.log(this.name);
}

// 函数对象有三个重要方法
test.call(obj);    // 立即执行,this 指向 obj
test.apply(obj);   // 立即执行,this 指向 obj  
test.bind(obj);    // 返回新函数,this 永久绑定到 obj

第二部分:this指向的确定

this指向有四种情况,分别为普通函数调用方法调用构造函数调用间接调用

情况1: 普通函数调用

javascript 复制代码
function func1() {
    console.log(this); //this 指向window (非严格模式)
}
func1(); // 独立调用

情况2: 方法调用

javascript 复制代码
var obj = {
    method: function() {
        console.log(this); // this 指向obj
    }
};
obj.method(); // 通过对象调用

情况3: 构造函数调用

javascript 复制代码
function Person(name) {
    this.name = name; // this 指向新创建的对象
}
var person = new Person("John");

情况4: 间接调用

javascript 复制代码
function func2() {
    console.log(this);
}
func2.call(obj); // this 指向 obj

this的指向取决于函数的调用方式,不同方式会产生不同的this指向,说明了this是动态的,不是静态的。

少侠请听题:

判断一下会输出什么?

javascript 复制代码
var name = "The Window"
var object = {
    name: "My object",
    getNameFunc: function() {
        return function() {
            return this.name; 
        };
    }
};
console.log(object.getNameFunc()());

答案是The Window

Why?因为是独立调用 ,返回的是一个立即执行函数,过程可以拆解为 var returnedFunc = object.getNameFunc()先获取到了函数,再执行returnedFunc()独立调用this 指向了window。问题的根源其实就是返回的函数失去了原来的对象上下文

那我们要输出My object怎么办?

方法一: 使用闭包来捕获变量

javascript 复制代码
var name = "The Window"
var object = {
    name: "My object",
    getNameFunc: function() {
    var that = this; // 添加这里
        return function() {
            return that.name; 
        };
    }
};

分析: object.getNameFunc()执行时,this指向了object,因为将this赋给了that,将object的引用保存到了that,返回内部函数,该函数形成了闭包,能够访问that,内部函数被独立调用 的时候,this指向了window,但that仍然指向object,于是就能够输出My object

方法二: 使用箭头函数

javascript 复制代码
var name = "The Window"
var object = {
    name: "My object",
    getNameFunc: function() {
        return () => {
            return this.name; 
        };
    }
};

分析: object.getNameFunc() 执行时,this 指向 object,由于箭头函数没有自己的this,定义时this就确定了,不会在调用时改变(词法作用域 ),this会继承所在作用域(即 getNameFunc)的 this,指向 object。于是也能够输出My object

方法三: 使用bind方法

javascript 复制代码
var name = "The Window"
var object = {
    name: "My object",
    getNameFunc: function() {
        return function() {
            return this.name;
        }.bind(this); // 显式绑定 this
    }
};

总结

函数作为对象的特性(有方法、有属性、可以形成闭包)提供了多种解决 this 指向问题的工具和方法。

相关推荐
尽兴-3 分钟前
问题记录:数据库字段 `CHAR(n)` 导致前端返回值带空格的排查与修复
前端·数据库·mysql·oracle·达梦·varchar·char
DsirNg8 分钟前
Vue 3:我在真实项目中如何用事件委托
前端·javascript·vue.js
克喵的水银蛇8 分钟前
Flutter 适配实战:屏幕适配 + 暗黑模式 + 多语言
前端·javascript·flutter
冬男zdn12 分钟前
Next.js 16 + next-intl App Router 国际化实现指南
javascript·typescript·reactjs
有意义30 分钟前
this 不是你想的 this:从作用域迷失到调用栈掌控
javascript·面试·ecmascript 6
前端涂涂32 分钟前
第2讲:BTC-密码学原理 北大肖臻老师客堂笔记
前端
能不能送我一朵小红花1 小时前
基于uniapp的PDA手持设备红外扫码方案
前端·uni-app
风止何安啊1 小时前
别被 JS 骗了!终极指南:JS 类型转换真相大揭秘
前端·javascript·面试
拉不动的猪1 小时前
深入理解 Vue keep-alive:缓存本质、触发条件与生命周期对比
前端·javascript·vue.js
|晴 天|1 小时前
WebAssembly:为前端插上性能的翅膀
前端·wasm