iT邦幫忙

1

JavaScript-基礎篇-This指向問題-下

  • 分享至 

  • xImage
  •  

2. Arrow function 的this指向

上篇回顧:

1. 默認綁定: console.log(this=== window)  ==> true 
2. 隱式綁定: (誰呼叫就指向誰) :
3. 顯式綁定: call, apply, bind
4. new 綁定規則;

箭頭函式的this

物件中的巢狀函式

    let a = 0
    let obj = {
        a : 'obj',
        foo(){
        let that = this;
        console.log(this);
        function test(){
            console.log(this); // // window
            console.log(that); // obj
        }
        test() 

        // 也可以通過這種方式使 this 指向 obj 👇🏻
        test.call(this)
    }
    }
    obj.foo()

箭頭函式中的this

    let a = 0
    let obj = {
        a: 'obj',
        foo() {
            console.log(this); // obj

            let test = ()=>{
                console.log(this); // obj
            }
            test()
        }
    }
    obj.foo()

    // => 箭頭函式內部沒有 this 指向, 箭頭函式的 this 指向是由外層函式的作用域決定的

能否更改箭頭函式的this指向?

    function foo(){
        let test = ()=>{
            console.log(this);
        }
        return test
    }

    let obj1 = {
        a: 'obj1',
        foo
    }

    let obj2 = {
        a: 'obj2',
        foo
    }

    obj1.foo()() // 打印obj1
    obj2.foo()() // 打印obj2

    // => 默認綁定規則(純粹調用) 對箭頭函式無效, 因為箭頭函式里面沒有 this

嘗試隱式綁定this指向

    let obj1 = {
        a: 'obj1',
        foo: ()=>{
            console.log(this)
        }
    }
    obj1.foo() // window

    // => 隱式綁定 對箭頭函式無效

嘗試顯式綁定this指向

    function foo(){
        let test = ()=>{
            console.log(this);
        }
        return test
    }
    let obj1 = {
        a: 'obj1',
        foo
    }

    foo()() // window
    let bar = foo().call(obj1) // window

    // => 顯式綁定 對箭頭函式無效

new 運算子 能否改變箭頭函式的 this 指向?

    let foo = ()=>{
        console.log(this);
    }
    let test = new foo()
    // 報錯 Uncaught TypeError: foo is not a constructor
    // => 箭頭函式不能作為建構式


    // => 所有綁定規則對箭頭函式都不適用; 箭頭函式的 this 取決於父環境中的 this 指向; => 箭頭函式不存在 this

案例一

    var name = '我是window裡的name'
    let obj1 = {
        name: 'obj1的name',
        fn1(){
            console.log(this.name);
        },
        fn2: ()=>{
            console.log(this.name);
        },
        fn3(){
            return function(){
                console.log(this.name);
            }
        },
        fn4(){
            return ()=>{
                console.log(this.name);
            }
        }
    }
    let obj2 = {
        name : 'obj2的name'
    }

    obj1.fn1(); // ?
    obj1.fn1.call(obj2); // ?

    obj1.fn2(); // ?
    obj1.fn2.call(obj2); // ?

    obj1.fn3()(); // ?
    obj1.fn3().call(obj2); // ?
    obj1.fn3.call(obj2)(); // ?

    obj1.fn4()() // ?
    obj1.fn4().call(obj2); // ?
    obj1.fn4.call(obj2)(); // ?
答案: 
    obj1.fn1(); // 'obj1的name'
    obj1.fn1.call(obj2); // 'obj2的name'

    obj1.fn2(); // '我是window里的name'
    obj1.fn2.call(obj2); // '我是window裡的name'

    obj1.fn3()(); // '我是window裡的name'
    obj1.fn3().call(obj2); // 'obj2的name'
    obj1.fn3.call(obj2)(); // '我是window裡的name'

    obj1.fn4()() // 'obj1的name'
    obj1.fn4().call(obj2); // obj1的name
    obj1.fn4.call(obj2)(); // obj2的name

案例二

    function Foo(){
        getName = function(){
            console.log(1)
        }
        return this
    }
    Foo.getName = function(){
        console.log(2);
    }
    Foo.prototype.getName = function(){
        console.log(3);
    }
    let getName = function(){
        console.log(4)
    }
    function getName(){
        console.log(5)
    }

    // 請寫出輸出結果: 
    Foo.getName(); // ?
    getName(); // ?
    Foo().getName(); // ?
    getName(); // ?

    new Foo.getName(); // ?
    new Foo().getName(); // ?
    new new Foo().getName(); // ?
答案: 
    Foo.getName(); // 2
    getName(); // 4
    Foo().getName(); // 1
    getName(); // 1

    new Foo.getName(); // 2
    new Foo().getName(); // 3
    new new Foo().getName(); // 3

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
greenriver
iT邦研究生 5 級 ‧ 2023-02-14 09:03:00

感謝分享
很有用又詳細的資料
/images/emoticon/emoticon41.gif

我要留言

立即登入留言