• 玩转TypeScript之你真的了解this所指对象吗


    hello,大家好呀这里是X,中秋节刚过去,现在又回到认真工作的状态中,最近也结束了答辩,比较放松休闲一些,一周至少一篇的typescript这就来了,这次是对“this”问题产生自己的想法和观点,喜欢的朋友可以点赞收藏,那么你对这个this了解到底有多深呢?
    以下的很多一些观点和知识来自我学习的笔记和网络,共同学习进步🥂

    在这里插入图片描述

    学习如何在JavaScript里正确使用this就好比一场成年礼。 由于TypeScript是JavaScript的超集,TypeScript程序员也需要弄清this工作机制并且当有bug的时候能够找出错误所在。 幸运的是,TypeScript能通知你错误地使用了this的地方。 🎈

    this和箭头函数

    JavaScript里,this的值在函数被调用的时候才会指定。 这是个既强大又灵活的特点,但是你需要花点时间弄清楚函数调用的上下文是什么。 但众所周知,这不是一件很简单的事,尤其是在返回一个函数或将函数当做参数传递的时候

    来个例子:

    let deck = {
        suits: ["hearts", "spades", "clubs", "diamonds"],
        cards: Array(52),
        createCardPicker: function() {
            return function() {
                let pickedCard = Math.floor(Math.random() * 52);
                let pickedSuit = Math.floor(pickedCard / 13);
                return {suit: this.suits[pickedSuit], card: pickedCard % 13};
            }
        }
    }
    let cardPicker = deck.createCardPicker();
    let pickedCard = cardPicker();
    alert("card: " + pickedCard.card + " of " + pickedCard.suit);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    可以看到createCardPicker是个函数,并且它又返回了一个函数。 如果我们尝试运行这个程序,会发现它并没有弹出对话框而是报错了。 因为createCardPicker返回的函数里的this被设置成了window而不是deck对象。 因为我们只是独立的调用了cardPicker()。 顶级的非方法式调用会将this视为window。 (注意:在严格模式下,this为undefined而不是window)。

    在这里插入图片描述
    那么我们该如何解决这个问题呢?

    为了解决这个问题,我们可以在函数被返回时就绑好正确的this。 这样的话,无论之后怎么使用它,都会引用绑定的‘deck’对象。 我们需要改变函数表达式来使用ECMAScript 6箭头语法。 箭头函数能保存函数创建时的this值,而不是调用时的值,再来看看修改之后的效果

    在这里插入图片描述

    this参数

    不幸的是,this.suits[pickedSuit]的类型依旧为any。 这是因为this来自对象字面量里的函数表达式。 修改的方法是,提供一个显式的this参数。 this参数是个假的参数,它出现在参数列表的最前面:

    想要直接绑定Desk对象,而不是window或者undefined,可以直接这样玩:

    let deck3: Deck = {
        suits: ["hearts", "spades", "clubs", "diamonds"],
        cards: Array(52),
        // NOTE: The function now explicitly specifies that its callee must be of type Deck
        createCardPicker: function(this: Deck) {
            return () => {
                let pickedCard = Math.floor(Math.random() * 52);
                let pickedSuit = Math.floor(pickedCard / 13);
                console.log("deck3:"+this.suits);
                return {suit: this.suits[pickedSuit], card: pickedCard % 13};
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    可以看到在定义函数的时候,function里的参数为this:Desk,这样子话是不是非常好理解呢😎

    在这里插入图片描述
    它的效果和上面的箭头函数效果一致,这里做了一个简单的测试:
    测试代码如下

    interface Card {
        suit: string;
        card: number;
    }
    interface Deck {
        suits: string[];
        cards: number[];
        createCardPicker(this: Deck): () => Card;
    }
    let deck2:Deck = {
        suits: ["hearts", "spades", "clubs", "diamonds"],
        cards: Array(52),
        createCardPicker: function() {
            // NOTE: the line below is now an arrow function, allowing us to capture 'this' right here
            return () => {
                let pickedCard = Math.floor(Math.random() * 52);
                let pickedSuit = Math.floor(pickedCard / 13);
                console.log("deck2:"+this.suits);
                return {suit: this.suits[pickedSuit], card: pickedCard % 13};
            }
        }
    }
    let deck3: Deck = {
        suits: ["hearts", "spades", "clubs", "diamonds"],
        cards: Array(52),
        // NOTE: The function now explicitly specifies that its callee must be of type Deck
        createCardPicker: function(this: Deck) {
            return () => {
                let pickedCard = Math.floor(Math.random() * 52);
                let pickedSuit = Math.floor(pickedCard / 13);
                console.log("deck3:"+this.suits);
                return {suit: this.suits[pickedSuit], card: pickedCard % 13};
            }
        }
    }
    let cardPicker2 = deck2.createCardPicker();
    let pickedCard2 = cardPicker2();
    let cardPicker3 = deck3.createCardPicker();
    let pickedCard3 = cardPicker3();
    console.log("card: " + pickedCard2.card + " of " + pickedCard2.suit);
    console.log("card: " + pickedCard3.card + " of " + pickedCard3.suit);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    在这里插入图片描述

  • 相关阅读:
    hibernate-validator后端表单数据校验的使用
    进程管理之wait和waitpid
    Flink同步Kafka数据到ClickHouse分布式表
    2024年软考重大改革
    智慧医院智能化方案
    学习——数据结构
    数据中心网络设计方案,数据中心网络解决方案
    Ubuntu24.04 LTS安装中文输入法
    计算机视觉+人工智能面试笔试总结——使用CNN进行图像分类
    J2EE项目部署与发布
  • 原文地址:https://blog.csdn.net/Xmumu_/article/details/126810271