日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無先后,達者為師

網(wǎng)站首頁 編程語言 正文

如何通過一道題,全方位地考察自己,是否已經(jīng)完美掌握了:this指向、作用域&作用域鏈、閉包、特殊數(shù)據(jù)類型?

作者:拯救世界的光太郎 更新時間: 2022-02-17 編程語言
inner = 'window';
function say() {
    console.log(inner);
    console.log(this.inner);
}
var obj1 = (function() {
    var inner = '1-1';
    return {
        inner: '1-2',
        say: function() {
            console.log(inner);
            console.log(this.inner);
        }
    }
})();
var obj2 = (function() {
    var inner = '2-1';
    return {
        inner: '2-2',
        say: function() {
            console.log(inner);
            console.log(this.inner);
        }
    }
})();

say();
obj1.say();
obj2.say();
obj1.say = say;
obj1.say();
obj1.say = obj2.say;
obj1.say();

蠻有意思的一道題,在對照答案之前,一定要先自己分析一下每一步的執(zhí)行結(jié)果!

// 答案:

window
window
1-1
1-2
2-1
2-2
window
1-2
2-1
1-2

我們按照順序一個一個來分析

? ?1.?say();

inner = 'window';
function say() {
    console.log(inner);  // window
    console.log(this.inner);  // window
}

say();

直接為 inner 賦值,那么就相當(dāng)于為 window 對象添加一個 inner 屬性,并賦值

函數(shù)被直接調(diào)用,等價于由 window 來調(diào)用 say 函數(shù),say() →?window.say()。所以 say 函數(shù)體內(nèi) this 也就指向 window,也就是函數(shù)體內(nèi)的 this.inner →?window.inner。

直接訪問 inner 屬性時,先在函數(shù)體內(nèi)尋找該屬性,沒有,就向上一層作用域?qū)ふ遥谌肿饔糜蛑姓业搅嗽搶傩裕蛴 ?/p>

? ?2.?obj1.say();

var obj1 = (function() {
    console.log( '1: ', this );  // 1:  Window{window: Window,...}
    var inner = '1-1';
    return {
        inner: '1-2',
        say: function() {
            console.log( '2: ', this );  // 2:  {inner: '1-2', say: ?}

            console.log('3: ', inner);  // 3:  1-1
            console.log('4: ', this.inner);  // 4:  1-2
        }
    }
})();

obj1.say();

首先,分析 obj1,obj1 保存一個自調(diào)用的匿名函數(shù)(IIFE)IIFE的調(diào)用者是 window,所以函數(shù)體內(nèi)打印的 this 自然就是一個 Window 類型的對象。

2 處打印的 this 也很容易理解,obj1 等于被 return 的對象 { inner: '1-2', say: function(){...} } ,obj1 調(diào)用 say 方法,也就相當(dāng)于 { inner: '1-2', say: function(){...} } 調(diào)用 say 方法,所以打印的 this 自然也就是這個對象了。

3 處打印 inner,say 函數(shù)體中沒有 inner 屬性,向上層尋找,這個 “上層” ,指代的是上層作用域,可以產(chǎn)生作用域的語句包括 if、while、switch 等判斷、循環(huán)語句,以及函數(shù)。也就是說,對象是不會產(chǎn)生作用域的,因此,say 函數(shù)體的上層作用域,其實對應(yīng)的是外層的匿名函數(shù) 函數(shù)體。那么直接打印 inner,找到的也就是在匿名函數(shù)中通過 var 定義的 inner 屬性。

4 處很簡單,上面我們已經(jīng)分析過對象中 say 函數(shù)的 this 指向,這里打印 this.inner 也就可以很直觀的看出來,也就等價于 { inner: '1-2', say: function(){...} }.inner。

? ?3.?obj2.say();

它和內(nèi)部的代碼和 obj1.say() 沒有實質(zhì)性的區(qū)別,分析方法和上面是一樣的。

? ?4.?obj1.say = say; obj1.say();

為了提升代碼整體的可讀性,我們對代碼進行一個小小的調(diào)整

inner = 'window';
function say() {
    console.log('1: ', inner);  // 1: window
    console.log('2: ', this.inner);  // 2: 1-2
}
var obj1 = (function() {
    var inner = '1-1';
    return {
        inner: '1-2',
        say: function() {
            console.log('3: ', inner);
            console.log('4: ', this.inner);
        }
    }
})();

obj1.say = say;
obj1.say();

這里考察的核心,其實就只有一點,就是函數(shù)究竟屬于什么類型?

如果可以肯定答案是引用類型,那么恭喜你,這道題基本已經(jīng)被你攻破了!

這么一來,我們就可以確定,對 obj1.say 進行重新賦值后,通過 obj1.say() 調(diào)用的say函數(shù),就應(yīng)該是調(diào)用的全局作用域中的 say 函數(shù)。

能把這一點分析出來,基本上這道題最難的點就已經(jīng)被我們拿下了。

把上面的點分析出來后,千萬不能迷糊!我們是調(diào)用全局作用域中的 say 方法,并不是把全局作用域的 say 方法放到 obj1 里面。

分析出來上一點后,下面就是常規(guī)的套路,函數(shù)體內(nèi)沒有 inner,就去上一層作用域中查找,找到了全局作用域中的 inner。

由 obj1 調(diào)用的say方法,那么 this 就指向 obj1,this.inner 自然就是 { inner: '1-2', say: function() {...} } 對象的 inner 屬性。

? ?5.?obj1.say = obj2.say; obj1.say();

var obj1 = (function() {
    var inner = '1-1';
    return {
        inner: '1-2',
        say: function() {
            console.log('1: ', inner);
            console.log('2: ', this.inner);
        }
    }
})();
var obj2 = (function() {
    var inner = '2-1';
    return {
        inner: '2-2',
        say: function() {
            console.log('3: ', inner);  // 3: 2-1
            console.log('4: ', this.inner);  // 4: 1-2
        }
    }
})();

obj1.say = obj2.say;
obj1.say();

這個時候,在來看這一題,是不是就發(fā)現(xiàn)太簡單了。

把 obj2 中的 say 方法賦給 obj1 的 say 屬性,前面已經(jīng)說過了,函數(shù)是引用類型。那么,在賦值后,我們通過 obj1.say() 調(diào)用的 say 方法,依舊是 obj2 的 say 方法。因此直接打印 inner 屬性時,向上層尋找,找的是 obj2 指向的匿名函數(shù)體的上下文,打印的自然就是 2-1。

由于是 obj1 調(diào)用的 say 方法,那么 this 指向的也是 obj1 中被返回的對象:{ inner: '1-2', say: function() {...} },所以打印出來的自然也就是 1-2 了。

原文鏈接:https://blog.csdn.net/qq_44647809/article/details/121694612

欄目分類
最近更新