真的!真的就一句话就能明白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"

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

函数对象的特殊方法

函数对象的原型链上有call、apply、bind等方法,这些方法能控制函数执行时的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 指向问题的工具和方法。

相关推荐
原则猫2 小时前
UDP 到底怎么实现可靠的
前端
Java后端的Ai之路2 小时前
14、ReactJS - 路由(Router)
前端·react.js·状态模式
持敬chijing2 小时前
白盒测试与代码审计-js登录逆向实战
javascript·网络·安全·web安全·网络安全·网络攻击模型
优选资源分享2 小时前
PicGo v3.0.3 新版 | 开源免费图床工具
javascript·笔记·electron
裕晟资质规划3 小时前
三类涉密资质延续时限差异分析:军工60日与集成印制3个月的边界
java·服务器·前端·网络·安全
ShineWinsu3 小时前
对于JavaScript:JavaScript基础语法的解析
开发语言·前端·javascript·面试·web·基础语法·循环
月夏3 小时前
Vue3 转 React:18 项对照表 + 5 个必踩的坑(附 7 天上手路线)
前端
广州华水科技3 小时前
单北斗GNSS位移监测系统的应用与维护解析
前端
普通人64 小时前
php+html+canvas实现树状打开的结构
开发语言·javascript·html5·1024程序员节
梦曦i4 小时前
uni-storage 0.1.0 发布:TTL过期管理+多实例隔离
前端·storage·uni-app x