• 玩转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

    在这里插入图片描述

  • 相关阅读:
    CGAL 计算点云的最值
    vue项目中显示第三方外部链接的页面
    小学生python游戏编程arcade----可旋转的坦克
    Springboot多数据源及事务实现方案
    Spring概述及IOC理论推导
    MongoDB综合实战篇(超容易)
    数据分析中数据规范化:小数定标规范化将一列数映射为0-1之间的数
    (一)Vue概述
    【SpringBoot】SpringBoot实现基本的区块链的步骤与代码
    ubuntu20.04安装ns3环境笔记
  • 原文地址:https://blog.csdn.net/Xmumu_/article/details/126810271