69781


下記の箇所がいまいち分からなくてみているのですが、コンストラクタ 内の実行順が上からではない気がします。Javascriptは非同期処理のためでしょうか？

**text-animation.js**

[code]

    class TextAnimation {
        constructor(el) {
            //elには<div class...が入ってる
            console.log(el);
            this.DOM = {};
            // 順番おかしい 分割された値が出てくる。
            const test = document.querySelector(el);
            console.log(test);
            if(el instanceof HTMLElement) {
                this.DOM.el = el;
            } else {
                this.DOM.el = document.querySelector(el);
            }
            this.chars = this.DOM.el.innerHTML.trim().split("");
            this.DOM.el.innerHTML = this._splitText();
        }
        _splitText() {
            return this.chars.reduce((acc, curr) => {
                curr = curr.replace(/\s+/, '&nbsp;');
                return `${acc}<span class="char">${curr}</span>`;
            }, "");
        }
        animate() {
            this.DOM.el.classList.toggle('inview');
        }
    }
    class TweenTextAnimation extends TextAnimation {
        constructor(el) {
            super(el);
            this.DOM.chars = this.DOM.el.querySelectorAll('.char');
        }
        
        animate() {
            this.DOM.el.classList.add('inview');
            this.DOM.chars.forEach((c, i) => {
                TweenMax.to(c, .6, {
                    ease: Back.easeOut,
                    delay: i * .05,
                    startAt: { y: '-50%', opacity: 0},
                    y: '0%',
                    opacity: 1
                });
            });
        }
    }
    
[/code]

**main.js**

[code]

    document.addEventListener('DOMContentLoaded', function () {
    //Intersectionは交差、Observerは監視する物。
        //<div class="animate-title"...</div>挟まれた要素まで取得できる。allだから同じ物をリストにして返してくれる。
        //監視したい要素がリストで格納される。
        const els = document.querySelectorAll('.animate-title');
        //このentriesはio.observe(child)、io.observe(child2)...のように監視する対象が複数ある場合にこちらにentriesに格納される。
        //関数だから順番は合ってる。コールバック関数として渡される。
        const cb = function(entries, observer) {
            entries.forEach(entry => {
                if(entry.isIntersecting) {
                    // entry.targetはelに値する。
                    // 最初はentry.targetが.animate-titleだった。
                    const ta = new TextAnimation('.animate-title')
                    ta.animate();
                    //entry.target.classList.add('inview');
                    // 監視を停止するには
                    observer.unobserve(entry.target);
                    
                } else {
                    // console.log('out view');
                    // entry.target.classList.remove('inview');
                }
                
            });
            //alert('intersectiong');
        }
    
        const options = {
            //交差対象にしたい親の要素を設定する事ができる。
            //今は画面に入るか入らないかだけど、それをタグないに入るかどうかで設定できる？
            root: null,
            //上から300pxの所で交差するように設定できる。
            //左右にも値を設定すると交差してない事になる。pxか%を付けないないとエラーになる。
            //              上    右  下   左
            rootMargin: "0px",
            //交差する部分の位置を設定できる。内側が0で外側が10.5で真ん中でも動作可能にする。
            threshold: 0
    
        }
    
        const io = new IntersectionObserver(cb, options);
        // queryselectorAllで取得したdiv要素
        els.forEach(el => io.observe(el));
    });
    
[/code]

自分の想定では分割前の `<div class="animate-title"...`
が出力されると思っていましたが、実際には分割された物がconsole.logで出力されました。

もう一つ気になった事が、コンストラクタ 内で下記のように変数を使用できると思っていたのですが、thisを付けないとtestは未定義と出ます。

[code]

    test = document.querySelector(el);
    console.log(test);
    
[/code]

Pythonでは似たような書き方でself無しでも実行できました。

この違いは非同期処理・同期処理の違いによるものなのでしょうか？

**Python での記述例:**

[code]

    class Person:
        def __init__(self, name, age):
            name2 = name
            print(name2)
            self.age = age
                
    taro = Person('太郎', 18)
    # 結果：太郎
    
[/code]

すいません。よろしくお願いします。

追記すいません。  
**index.html**  
分割するものを載せていませんでした。

[code]

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp" crossorigin="anonymous">
        <link href="https://fonts.googleapis.com/css2?family=Teko:wght@500&display=swap" rel="stylesheet">
        <link rel="stylesheet" href="style.css">
        <title>Document</title>
    </head>
    
    <body>
        <section>
    
            <div class="animate-title">Start where you are.</div>
    
        </section>
        <section>
    
            <div class="animate-title">Use what you have.</div>
    
        </section>
        <section>
    
            <div class="animate-title">Do what you can.</div>
    
        </section>
        <script src="text-animation.js"></script>
        <script src="main.js"></script>
    </body>
    
    </html>
    
[/code]


CC BY-SA 4.0
2020-08-22T03:33:41.023
69773
2020-08-23T02:25:14.037
2020-08-23T02:25:14.037
22565
22565
question
javascript html
Javascript のコンストラクタ 内で処理の実行順について


質問者が言っている具体的な違いがわからないのですが、書き換えられるDOMを`console.log()`で表示しようとしているようなので、その問題だと推測します。この回答は全く見当違いの可能性があります。

* * *

Google
Chromeで開発モードのConsoleを出した状態で、次のようなスニペットを実行しても再現できると思います。(他のブラウザでは現象が発生しない可能性があります。Google
Chromeでのみ確認しています。)

[code]

    const test = document.getElementById("test");
    console.log(test);
    test.innerHTML = "b";
    console.log(test);
[/code]

[code]

    <div id="test">a</div>
[/code]

次のようなログが出るでしょう。

[code]

    <div id="test">b</div>
    <div id="test">b</div>
    
[/code]

一回目の`console.log()`が実行されるとき、中身は"a"だったはずなので、これはおかしいと思うかも知れません。では、各行の実行が非同期なのかというとそうではありません。次を同じように実行してください。

[code]

    const test = document.getElementById("test");
    console.log(test.innerHTML);
    test.innerHTML = "b";
    console.log(test.innerHTML);
[/code]

[code]

    <div id="test">a</div>
[/code]

結果は次のようになるはずです。

[code]

    a
    b
    
[/code]

一体何が違うのかですが、これはChromeのコンソール表示の仕様による物です。`console.log()`自体は同期的に、オブジェクトをコンソールに渡します。しかし、コンソールで実際に表示される処理は非同期です。最初のコードでは、同じDOMを渡しています。このときDOMの中身のコピーが渡されるのではなく、DOMへの参照が渡されるだけに過ぎないことに注意してください。コンソールでは、それがDOMの場合は、HTMLとして表現します。この処理は`console.log()`とは分離された非同期な処理であるため、最初の`console.log()`で渡された物も、表示処理をするときには既に書き換わった物になっていると言うことです。

この現象は配列(Array)等でも発生します。書き換え不可な文字列など以外をコンソールログとして表示した場合は、コンソールに渡されたときの中身ではなく、コンソールで表示されるときの情報であるということに注意しなくてはなりません。

※ コンソールでどのような表示をするかはブラウザ依存であるため、他のブラウザでは結果が異なる場合があります。

* * *

もうひとつ。Pythonの例ですが、JavaScriptで書くとこうなります。

[code]

    class Person {
        constructor(name, age) {
            let name2 = name;
            console.log(name2);
            this.age = age;
        }
    }
    let taro = new Person('太郎', 18);
    // 結果：太郎
[/code]

Pythonは代入文を書くだけでローカル変数(トップレベルならグローバル変数)が宣言されたとみなされます。しかし、JavaScriptのstrictモードでは、`var`や`let`、`const`等を用いた宣言文が必要です。非strictモードでは、代入文を書くだけでグローバル変数として宣言されたとみなされますが、class構文の内部は強制的にstrictモードになるため、この仕様は使用できません。


CC BY-SA 4.0
2020-08-22T18:10:23.937
69781
2020-08-22T18:10:23.937
7347
69773
answer