真的!真的就一句话就能明白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 指向问题的工具和方法。

相关推荐
WeiXiao_Hyy36 分钟前
成为 Top 1% 的工程师
java·开发语言·javascript·经验分享·后端
吃杠碰小鸡1 小时前
高中数学-数列-导数证明
前端·数学·算法
kingwebo'sZone1 小时前
C#使用Aspose.Words把 word转成图片
前端·c#·word
xjt_09011 小时前
基于 Vue 3 构建企业级 Web Components 组件库
前端·javascript·vue.js
我是伪码农1 小时前
Vue 2.3
前端·javascript·vue.js
夜郎king2 小时前
HTML5 SVG 实现日出日落动画与实时天气可视化
前端·html5·svg 日出日落
辰风沐阳2 小时前
JavaScript 的宏任务和微任务
javascript
夏幻灵3 小时前
HTML5里最常用的十大标签
前端·html·html5
冰暮流星3 小时前
javascript之二重循环练习
开发语言·javascript·数据库
Mr Xu_3 小时前
Vue 3 中 watch 的使用详解:监听响应式数据变化的利器
前端·javascript·vue.js