Last active
March 18, 2020 22:02
-
-
Save nukisashineko/39c38f4225048ea790f5e9540d1a620d to your computer and use it in GitHub Desktop.
nwtgckとの会話の派生でAsyncFunction isなんぞやって確認
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// MDN: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/AsyncFunction | |
// 参考:https://javascript.developreference.com/article/14715429/ES+2017%3A+async+function+vs+AsyncFunction(object)+vs+async+function+expression | |
// Q何しようとしたの? | |
// A友人が話していたAsyncFunctionオブジェクトを触ってみる | |
// async function が利用するPromiseはグローバルではなくその場でのスコープ変数らしい。 | |
// AsyncFunctionがスコープ変数を参照できなくしているのってPromiseが動的に書き換えられると面倒だからじゃない?って思ったので実験した | |
// 結果はまあよくわからなかった。 | |
// console.logでの比較式は出力結果と並べてtrueになるようにしている | |
// 検証はChrome 80.0.3987.132 | |
// グローバル変数を書き換えるので、e.g.間ではタブをリロードして初期化すること | |
// e.g. 1 グローバルは書き換えない | |
let NativePromise = Promise; | |
class CustomPromiseImplementation extends Promise { }; | |
// Promiseだけだと糖衣構文が主でわかりにくかったのでFooも追加してわかりやすく | |
class AbstructFoo { constructor() { } }; | |
class Foo extends AbstructFoo { constructor() { super(); } }; | |
let NativeFoo = Foo; | |
class CustomFoo extends AbstructFoo { constructor() { super(); } }; | |
console.log([ | |
Promise.resolve() instanceof Promise === true, | |
(async () => { })() instanceof Promise === true, | |
(async () => { })() instanceof NativePromise === true, | |
(new Foo()) instanceof NativeFoo === true, | |
(new Foo()) instanceof CustomFoo === false, | |
]); | |
// e.g 2 グローバル変数を書き換える (参考のURLにあったやつ) | |
let NativePromise = Promise; | |
class CustomPromiseImplementation extends Promise { }; | |
class AbstructFoo { constructor() { } }; | |
class Foo extends AbstructFoo { constructor() { super(); } }; | |
let NativeFoo = Foo; | |
class CustomFoo extends AbstructFoo { constructor() { super(); } }; | |
// Promise,Fooを書き換え | |
Promise = CustomPromiseImplementation; | |
Foo = CustomFoo; | |
console.log([ | |
Promise.resolve() instanceof Promise === true, | |
(async () => { })() instanceof Promise === false, | |
(async () => { })() instanceof NativePromise === true, | |
(new Foo()) instanceof NativeFoo === false, | |
(new Foo()) instanceof CustomFoo === true, | |
]); | |
// e.g. 3 ローカル変数として書き換える | |
let NativePromise = Promise; | |
class CustomPromiseImplementation extends Promise { }; | |
class AbstructFoo { constructor() { } }; | |
class Foo extends AbstructFoo { constructor() { super(); } }; | |
let NativeFoo = Foo; | |
class CustomFoo extends AbstructFoo { constructor() { super(); } }; | |
let a = 'global'; | |
(function () { | |
// Promise, Fooをローカル変数として書き換え | |
let Promise = CustomPromiseImplementation; | |
let Foo = CustomFoo; | |
console.log([ | |
Promise.resolve() instanceof Promise === true, | |
(async () => { })() instanceof Promise === false, | |
(async () => { })() instanceof NativePromise === true, | |
(new Foo()) instanceof NativeFoo === false, | |
(new Foo()) instanceof CustomFoo === true, | |
]); | |
})(); | |
// AsyncFunctionでPromise, Fooをローカル変数として書き換え | |
(function () { | |
return Object.getPrototypeOf(async function () { }).constructor(` | |
let Promise = CustomPromiseImplementation; | |
let Foo = CustomFoo; | |
let a = 'inner asyncfuncconstructer'; | |
return [ | |
Promise.resolve() instanceof Promise === true, | |
(async () => {})() instanceof Promise === false, | |
(async () => {})() instanceof NativePromise === true, | |
(new Foo()) instanceof NativeFoo === false, | |
(new Foo()) instanceof CustomFoo === true, | |
a === 'inner asyncfuncconstructer', | |
];`)().then(function(resolve){ | |
console.log(resolve); | |
}); | |
})(); | |
// e.g. 4 スコープ変数として書き換え。通常の無名関数と比べてみたり、AsyncFunctionと比べてみたりする。 | |
let NativePromise = Promise; | |
class CustomPromiseImplementation extends Promise { }; | |
class AbstructFoo { constructor() { } }; | |
class Foo extends AbstructFoo { constructor() { super(); } }; | |
let NativeFoo = Foo; | |
class CustomFoo extends AbstructFoo { constructor() { super(); } }; | |
let a = 'global'; | |
// 無名関数内でスコープ変数として書き換え | |
let normalfunc = (function () { | |
let Promise = CustomPromiseImplementation; | |
let Foo = CustomFoo; | |
let a = 'inner normalfunc'; | |
// e.g. 3 と同じ結果。ちゃんとスコープ変数で束縛されている普通だな。 | |
return function () { | |
console.log([ | |
Promise.resolve() instanceof Promise === true, | |
(async () => { })() instanceof Promise === false, | |
(async () => { })() instanceof NativePromise === true, | |
(new Foo()) instanceof NativeFoo === false, | |
(new Foo()) instanceof CustomFoo === true, | |
a === 'inner normalfunc', | |
]); | |
}; | |
})(); | |
// async function内でスコープ変数として書き換え | |
let asyncfunc = (function () { | |
let Promise = CustomPromiseImplementation; | |
let Foo = CustomFoo; | |
let a = 'inner asyncfunc'; | |
// e.g. 3 と同じ結果。 | |
// ー>ちゃんとスコープ変数で束縛されている?なぜ?スコープ変数で束縛されないはずでは? | |
return async function () { | |
return [ | |
Promise.resolve() instanceof Promise === true, | |
(async () => { })() instanceof Promise === false, | |
(async () => { })() instanceof NativePromise === true, | |
(new Foo()) instanceof NativeFoo === false, | |
(new Foo()) instanceof CustomFoo === true, | |
a === 'inner asyncfunc', | |
]; | |
}; | |
})()(); | |
// AsyncFunction constructer内でスコープ変数として書き換え | |
let asyncfuncconstructer = (function () { | |
let Promise = CustomPromiseImplementation; | |
let Foo = CustomFoo; | |
let a = 'inner asyncfuncconstructer'; | |
// e.g.1 と同じ結果。 | |
// 結果がe.g.1と同じー>スコープ束縛せずにグローバル変数を参照している | |
return Object.getPrototypeOf(async function () { }).constructor(` | |
return [ | |
Promise.resolve() instanceof Promise === true, | |
(async () => {})() instanceof Promise ===true, | |
(async () => {})() instanceof NativePromise === true, | |
(new Foo()) instanceof NativeFoo === true, | |
(new Foo()) instanceof CustomFoo === false, | |
a === 'global' | |
];`) | |
})()(); | |
(function () { | |
let a = 'inner main'; | |
normalfunc(); | |
asyncfunc.then(function (resolve) { | |
console.log(resolve); | |
asyncfuncconstructer.then(function (resolve) { | |
console.log(resolve); | |
}); | |
}); | |
})(); | |
// e.g 5 ~async functionとAsyncFunctionは糖衣構文じゃなくて別物だよね(少なくともchromev80の実装では)ってことをe.g.1と同じように確認~ | |
// (追記)async functionとAsyncFunctionは糖衣構文、同じものを指すっぽい、呼び出し方指摘でinstanceofがtrue返すことを確認 | |
let NativePromise = Promise; | |
class CustomPromiseImplementation extends Promise {}; | |
class AbstructFoo { constructor() {} }; | |
class Foo extends AbstructFoo { constructor() { super(); } }; | |
let NativeFoo = Foo; | |
class CustomFoo extends AbstructFoo { constructor() { super(); } }; | |
console.log([ | |
Promise.resolve() instanceof Promise === true, | |
(async () => {})() instanceof Promise === true, | |
(async () => {})() instanceof NativePromise === true, | |
(async () => {})() instanceof CustomPromiseImplementation === false, | |
(async function(){})() instanceof Promise === true, | |
(async function(){})() instanceof NativePromise === true, | |
(async function(){})() instanceof CustomPromiseImplementation === false, | |
(Object.getPrototypeOf(async function () { }).constructor())() instanceof Promise === true, | |
(Object.getPrototypeOf(async function () { }).constructor())() instanceof NativePromise === true, | |
(Object.getPrototypeOf(async function () { }).constructor())() instanceof CustomPromiseImplementation === false, | |
(new Foo()) instanceof NativeFoo === true, | |
(new Foo()) instanceof CustomFoo === false, | |
]); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
激感謝!
e.g 5の
Object.getPrototypeOf(async function () { }).constructor()
は呼び出しが抜けたよ。ちょっとみづらくなるけど(Object.getPrototypeOf(async function () { }).constructor())()
みたいに呼び出しいるかな。他のe.g.だと付いてるのだけど。