指向 MutationObserver 的 this 为什么会是 undefined 啊? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a Javascript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
Javascript 权威指南第 5 版
Closure: The Definitive Guide
axo
V2EX    Javascript

指向 MutationObserver 的 this 为什么会是 undefined 啊?

  •  
  •   axo 2023-02-02 23:17:21 +08:00 2274 次点击
    这是一个创建于 1063 天前的主题,其中的信息可能已经有所发展或是发生改变。

    需求:MutationObserver 的回调内部需要 await 读取环境变量,且原子化的运行(前一次变动的回调没执行完前,不会有新的回调同时运行)

    只是简单地在回调里面用 await ,声明前加上 async ,显然不管用。于是尝试了下面的写法:回调里先把观察器断掉,等处理完其他事,返回前再连上。虽然写法很丑陋,且会丢掉一些变动没处理,但不影响使用场景:

    let ManualHider = function(rules) { this.run = function() { this.list_observer = new MutationObserver(this.callback); this.list_observer.observe(document.querySelector(this.matching_unique_rule.root), { childList: true }); } this.callback = async function() { this.list_observer.disconnect(); // 报错的行 await new Promise(r => setTimeout(r, 3000)); // do sth asynchronously this.list_observer.observe(document.querySelector(this.matching_unique_rule.root), { childList: true }); } }; new ManualHider(rules).run(); 

    但是当第二次触发时,this 会变成 undefined ,提示 Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'disconnect')。

    这是为什么呀?另外若这种写法实在不行,还有什么简单方法(太专业的搞不来…)能实现需求吗?谢谢

    (楼主文科生,偶尔代码仅自用,若说的不对,请大佬对业余者宽容谅解)

    13 条回复    2023-02-06 10:04:08 +08:00
    xy90321
        1
    xy90321  
       2023-02-02 23:26:09 +08:00 via iPhone   1
    另外搞一个队列,observer 的回调只负责往队列里面塞消息,另外开个处理去顺次消费队列里面的消息就可以了
    ie88
        2
    ie88  
       2023-02-02 23:41:31 +08:00   1
    this.run 和 this.callback 换成 arrow function 试试:() => {}
    axo
        3
    axo  
    OP
       2023-02-02 23:47:36 +08:00
    @ie88 #2 哇,原来是这个原因,没注意 箭头函数没有自己的 this 但普通函数有 这点,感谢老哥呀
    ie88
        4
    ie88  
       2023-02-02 23:54:08 +08:00   2
    @axo 我从某本书摘几句话给你,有空看看 ES6/7/Next
    - Insie a `normal function`, `this` is a reference to the context object that the function is operating on
    - Inside an `arrow function`, `this` refrences the context in which the arrow function expression is defined.
    - when used inside global `normal functions`, `this` is equal to `window` in nonstrict mode and `undefined` in strict mode
    lisongeee
        5
    lisongeee  
       2023-02-03 00:02:49 +08:00   1
    ```js
    let ManualHider = function(rules) {

    this.run = function() {
    this.list_observer = new MutationObserver(this.callback);
    this.list_observer.observe(document.querySelector(this.matching_unique_rule.root), {
    childList: true
    });
    }

    this.task = Promise.resolve()
    this.callback = ()=> {
    this.task = this.task.finally(async()=>{
    await new Promise(r => setTimeout(r, 3000));
    // do sth asynchronously
    })
    }
    };

    new ManualHider(rules).run();
    ```
    lisongeee
        6
    lisongeee  
       2023-02-03 00:06:55 +08:00   1
    确实还要把 this 。run=function(){ 换成 this 。run=()=>{
    lisongeee
        7
    lisongeee  
       2023-02-03 00:07:57 +08:00   1
    我使用 。而不是 . 是因为 V2EX 把上一条评论认为包含外链不让发送
    axo
        8
    axo  
    OP
       2023-02-03 00:17:58 +08:00
    @lisongeee #5 试了下,完美!以前没用过 finally ,真是又简洁又解决了问题!非常感谢大佬!笔芯
    autoxbc
        9
    autoxbc  
       2023-02-03 00:47:04 +08:00
    只是为了让一串异步函数顺序执行,没必要把观察者接来接去,只要把 promise 接起来就够了,也就两行代码

    let promise = Promise.resolve();
    const run = asyncFunction => promise = promise.then( () => asyncFunction() );

    const getAsyncFunction = name => async () => {
    console.log(`${ name } begin`);
    await new Promise( resolve => setTimeout( resolve , 3000 ) );
    console.log(`${ name } end`);
    };

    run( getAsyncFunction('f1') );
    run( getAsyncFunction('f2') );
    run( getAsyncFunction('f3') );
    justdoit123
        10
    justdoit123  
       2023-02-03 10:1:53 +08:00
    歪个楼,话说各位 js 们写业务代码还会用到 call/bind/apply 吗?我个人观点:js 里的 context bind 跟 C 语言里的 goto 一样,需要用到的场景已经很少了。
    wakarimasen
        11
    wakarimasen  
       2023-02-03 10:53:49 +08:00
    习惯上会这样写吧:

    function ManualHider(rules) {
    this.rules = rules;
    }
    ManualHider.prototype.run = function() {
    this.list_observer = new MutationObserver(this.callback);
    this.list_observer.observe(document.querySelector(this.matching_unique_rule.root), {
    childList: true
    });
    }

    ManualHider.prototype.callback = async function() {
    this.list_observer.disconnect(); // 报错的行
    await new Promise(r => setTimeout(r, 3000)); // do sth asynchronously
    this.list_observer.observe(document.querySelector(this.matching_unique_rule.root), {
    childList: true
    });
    }
    new ManualHider({}).run();
    wdssmq
        12
    wdssmq  
       2023-02-04 21:37:29 +08:00   1
    @mistkafka 遍历 nodeList 时用 - -
    justdoit123
        13
    justdoit123  
       2023-02-06 10:04:08 +08:00
    @wdssmq 是哦! 不过也确实少用了。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2389 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 21ms UTC 09:21 PVG 17:21 LAX 01:21 JFK 04:21
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86