博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
精简讨论Javascript 中的 this 问题
阅读量:5823 次
发布时间:2019-06-18

本文共 3901 字,大约阅读时间需要 13 分钟。

前言

最近看了一些文章都有谈论 this 的问题。其实,总觉得并没想象那么难(傲娇脸...)。所以,我在此就想分享一下我的极简理解,也希望能帮助到大家~~~~

情况一:谁调用,this 就指向那个对象。

话不多说,直接用例开干。 例一:

// 1. 直接调用function getAge() {    var age = 18    console.log(this.age)   // undefined    console.log(this)       // window}getAge()   复制代码

分析:getAge 是谁调用的?

  • 写完整的话应该是 window.getAge().
  • 调用对象就是 window,所以函数内部上下文环境就是 window.
  • 当前环境下没有 window.age ,所以就是 undefined 啦.

注: 严格模式下, window 环境下调用的函数的this 是 undefined,不指向 window。

'use strict'function getAge() {    var age = 18    // console.log(this.age)   // 直接语法报错,undefined 无法再找属性    console.log(this)       // undefined}getAge() 复制代码

例二:

// 2. 对象调用var obj = {    age: 19,    getAge() {        console.log(this.age)        console.log(this)    },    returnGetAgeFunc() {        return this.getAge    }}obj.getAge()obj.returnGetAgeFunc()()复制代码

首先是 obj.getAge(),答案是 19obj这个对象

  • 这个 getAge 就是 obj,所以上下文环境是 obj 无可厚非。 所以第一个答案是 小明2,第二个答案是 obj 这个对象。

然后是 obj.returnGetAgeFunc() (), 答案是 undefinedwindow

  • 首先是 obj.returnGetAgeFunc() 得到的就是 this.getAge 这个函数, 因此 obj.returnGetAgeFunc() === getAge
  • 接着,当前的 getAge 不就在全局环境(window)下执行嘛,等同于例一,所以 this 就是 window,window.age 就是 undefined呗。

例三:

// 3. 嵌套深一层var obj = {    age: 19,        innerObj: {        getAge() {            console.log(this.age)            console.log(this)        },        returnGetAgeFunc() {            return this.getAge        }    }}obj.innerObj.getAge()   // undefined   innerObjobj.innerObj.returnGetAgeFunc()()复制代码

分析:

  • obj.innerObj 简单来说就是 innerObj 对象, 然后用 innerObj调用函数,当前 this 不就是 innerObj嘛。所以,age 是 obj 的属性,因此, this.age === undefined. this 指向就是 innerObj
  • 第二个同理,obj.innerObj.returnGetAgeFunc() 这么长一截就是为了取出 obj.innerObj 中的 getName 函数。然后在 Window 环境下执行。this.age === undefined, this 指向就是 Window。

再用代码等量代换一次...别嫌我啰嗦,因为,和一些人讲过,但是他们没懂.. ~。~

var obj = {    age: 19,    innerObj: {        getAge() {            console.log(this.age)            console.log(this)        },        returnGetAgeFunc() {            return this.getAge        }    }}obj.innerObj.getAge()obj.innerObj.returnGetAgeFunc()()// 使用上完全等价下面var innerObj: {    getAge() {        console.log(this.age)        console.log(this)    },    returnGetAgeFunc() {        return this.getAge    }}innerObj.getAge()function getAge() {    console.log(this.age)    console.log(this)}// obj.innerObj.returnGetAgeFunc() == getNamegetName()   // obj.innerObj.returnGetAgeFunc()()复制代码

情况二:自行改变当前环境下的this指向。

完全复制之前的事例,加一点东西来解释,尽可能的减少过多冗余信息接收。

改变执行函数内部 this 指向的有三个函数, call, apply, bind. 这里就不解释这三个函数的差异了。默认大家都知道~

// 1. 直接调用var obj = {}obj.age = 20function getAge() {    var age = 18    console.log(this.age)   // 20    console.log(this)       // obj}getAge.call(obj)复制代码

其实挺容易理解的,就是把函数的执行上下文环境的 this 换成了 obj。

同理:

// 2. 对象调用var tempObj = { age: 20 }var obj = {    age: 19,    getAge() {        console.log(this.age)        console.log(this)    },    returnGetAgeFunc() {        return this.getAge    }}obj.getAge.call(tempObj)    // 20    tempObjobj.returnGetAgeFunc().call(tempObj)    //  20    tempObj复制代码

最后一个就不用多说了。这里再补充一些。

比如通过 new 关键字得到的对象,调用内部函数时,this 指向的就是这个对象,其实就是使用了上述 call,apply,bind 函数来改变的。

情况三: ES6 箭头函数

使用箭头函数编程往往也被称为函数式编程,也是面向过程编程。 当我们从上往下的编写业务的时候,很多情况下,我们希望this 的指向是一致的,特别是回调函数中的 this。

因此,简单来说,this 指向

// 2. 对象调用var tempObj = { age: 20 }var obj = {    nonArrowFunc() {        // this === obj        return function() {            console.log(this)   // tempObj            console.log(this.age)   // 20        }    },    arrowFunc() {        // this === obj        return () => {            console.log(this)   // obj            console.log(this.age)   // undefined        }    }}obj.nonArrowFunc().call(tempObj)obj.arrowFunc().call(tempObj)    //  20    tempObj复制代码

没有箭头函数时,上下文环境被更换成了 tempObj 使用箭头函数后,上下文环境使用运行环境的this.

再简单的说就是,箭头函数里面的this 不用自己函数上下文环境中的,用上一级的。

总结

因此,我归纳的 this 就是这三种,一般业务情况下,我们都不会搞得很复杂,this指向有问题,我们也会用一个变量来承接解决。 但是,面试的时候可能会比较多层,比较绕。如果不熟练的话,只需要按照我的第二种情况去等量替换,你就容易得到结果啦~

转载于:https://juejin.im/post/5cc8292be51d456e361ed981

你可能感兴趣的文章
JDBC二查询(web基础学习笔记八)
查看>>
监听器(web基础学习笔记二十二)
查看>>
802.11 学习笔记
查看>>
Leetcode-Database-176-Second Highest Salary-Easy(转)
查看>>
构建Docker Compose服务堆栈
查看>>
最小角回归 LARS算法包的用法以及模型参数的选择(R语言 )
查看>>
Hadoop生态圈-Kafka常用命令总结
查看>>
如何基于Redis Replication设计并实现Redis-replicator?
查看>>
Linux 环境下 PHP 扩展的编译与安装 以 mysqli 为例
查看>>
浮点数内存如何存储的
查看>>
贪吃蛇
查看>>
EventSystem
查看>>
用WINSOCK API实现同步非阻塞方式的网络通讯
查看>>
玩一玩博客,嘿嘿
查看>>
P1352 没有上司的舞会
查看>>
ios11文件夹
查看>>
【HLOJ 559】好朋友的题
查看>>
Electric Fence(皮克定理)
查看>>
nvl 在mysql中如何处理
查看>>
MyEclipse 快捷键
查看>>