日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

this全面解析, 如何定位this指向,一文总结,再也不怕面试官追问啦

發(fā)布時間:2024/9/27 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 this全面解析, 如何定位this指向,一文总结,再也不怕面试官追问啦 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一、調(diào)用位置

在理解this的綁定過程之前,首先要理解調(diào)用位置:調(diào)用位置就是函數(shù)在代碼中被調(diào)用的位置(而不是申明的位置)。只有仔細分析調(diào)用位置才能回答這個問題:這個this到底引用的是什么?

function foo() {console.log('foo')// 當前調(diào)用棧是: bar// 因此,當前調(diào)用位置在bar中 }function bar() {console.log('bar')// foo當前調(diào)用位置foo()// 當前調(diào)用棧是: bar// 因此,當前調(diào)用位置在bar中 }function baz() {console.log('baz')// bar當前調(diào)用位置bar()// 當前調(diào)用棧是: baz// 因此,當前調(diào)用位置是全局作用域 }// baz當前調(diào)用位置 // 全局作用域 baz()

二、綁定規(guī)則

1、默認綁定(非嚴格模式):獨立函數(shù)調(diào)用

const a = 2 function foo() {console.log(this.a) } foo() // 2 // foo() 在這里直接食用不帶任何修飾的函數(shù)引用進行調(diào)用,因此只能使用默認綁定;調(diào)用位置為全局作用域,因此this默認綁定到全局作用域。

2、隱式綁定:調(diào)用位置是否有上下文,或者說是否被某個對象擁有或者包含

  • 當函數(shù)引用有上下文對象時,隱式綁定規(guī)則會把函數(shù)調(diào)用中this綁定到這個上下文對象上。
function foo() {console.log(this.a) } const obj = {a: 2,foo: foo } obj.foo() // 2// 注意: 首先需要注意的是foo()的聲明方式,及其之后是如何北方做引用屬性添加到obj中的。但是無論是直接在obj中定義還是先定義在添加為引用屬性,這個函數(shù)嚴格來說都不屬于obj對象。 // 然而,調(diào)用位置會使用obj上下文來引用函數(shù),因此你可以說函數(shù)被調(diào)用時obj對象‘擁有’或‘包含’它。// 當函數(shù)引用有上下文對象時,隱式綁定規(guī)則會把函數(shù)調(diào)用中this綁定到這個上下文對象上。

對象屬性引用鏈中只有 最頂層 或者說 最后一層 會影響調(diào)用位置

function foo() {console.log(this.a) } const obj1 = {a: 2,foo: obj2 } const obj2 = {a: 42,foo: foo } obj1.obj2.foo() // 42

隱式丟失:一個最常見的this綁定問題就是 被隱式綁定的函數(shù) 會丟失綁定對象,也就是說它會引用默認綁定,從而把this綁定到全局對象或者undefined上,取決于是否是嚴格模式。

function foo() {console.log(this.a) } const obj = {a: 2,foo: foo } const bar = obj.foo // 函數(shù)別名! const a = '我是全局對象' bar() // -> 我是全局對象 // 雖然bar是obj.foo的一個引用,但是實際上,他引用的是foo函數(shù)本身,因此此時的 bar() 相當于 foo(), 是一個不帶任何修飾的函數(shù)調(diào)用,因此應(yīng)用了默認綁定 function foo() {console.log(this.a) } function doFoo(fn) {// fn其實引用的是foofn() // <--調(diào)用位置! } const obj = {a: 2,foo: foo } const a = '我是全局對象' doFoo(foo) // -> 我是全局對象 // 參數(shù)傳遞其實就是一種隱式賦值,因此我們傳入函數(shù)時也會被隱式賦值,所以結(jié)果和上一個例子一樣 // 如果把函數(shù)傳入語言內(nèi)置的函數(shù)而不是自定義的函數(shù),會怎么樣吶?結(jié)果是一樣的,沒有區(qū)別 function foo() {console.log(this.a) } const obj = {a: 2,foo: foo } const a = '我是全局對象' setTimeout(obj.foo, 100) // -> 我是全局對象// JavaScript環(huán)境中內(nèi)置的setTimeout()函數(shù)實現(xiàn)和下面的代碼類似: function setTimeout(fn, delay) {// 等待delay毫秒fn() // <--調(diào)用位置! }

3、顯式綁定

function foo() {console.log(this.a) } const obj = {a: 2, } foo.call(obj) // -> 2 // 通過foo.call(...)可以在調(diào)用foo時強制把它綁定到obj上// 思考下面代碼輸出什么 const b = '我是全局對象' function foo() {console.log(this.b) } const obj = {b: 2,foo: foo } const bar = function(fn) {fn() } bar.call(obj, foo) // -> 我是全局對象// 顯然,通過這種方式還是無法解決綁定丟失問題

3.1、硬綁定

function foo() {console.log(this.b) } const obj = {b: 2, } const bar = function() {foo.call(obj) } bar() // -> 2 // 硬綁定的bar不能再修改它的this bar.call(window) // -> 2

由于硬綁定是一種非常常用的模式。所以在es5中提供了內(nèi)置的方法Funtion.prototype.bind
bind(…)會返回一個硬編碼的新函數(shù),它會吧參數(shù)設(shè)置為this的上下文并調(diào)用原始函數(shù)

function foo(something) {console.log(this.a, something)return this.a + something } const obj = {a: 2, } const bar = foo.bind(obj) const b = bar(3) // -> 2 3 console.log(b) // -> 5

4、new綁定
使用new來調(diào)用函數(shù),或者說發(fā)生構(gòu)造函數(shù)調(diào)用時,它會自動執(zhí)行下面的操作:

  • 創(chuàng)建(構(gòu)造)一個全新的對象
  • 這個新對象會被執(zhí)行[[原型]]鏈接(將這個對象的_proto_指向其構(gòu)造函數(shù)的原型)
  • 這個新對象會綁定到函數(shù)調(diào)用(構(gòu)造函數(shù))的this
  • 如果函數(shù)沒有返回其他對象,那么new表達式中的函數(shù)調(diào)用會自動返回這個新對象
  • function foo(a) {this.a = a } const bar = new foo(2) console.log(bar.a) // -> 2

    三、優(yōu)先級

    如果某個調(diào)用位置同時使用四條規(guī)則,那誰的優(yōu)先級更高呢?
    1、隱式綁定與顯式綁定誰的優(yōu)先級更高?

    function foo() {console.log(this.a) } const obj1 = {a: 2,foo: foo } const obj2 = {a: 3,foo: foo } obj1.foo() // -> 2 obj2.foo() // -> 3obj1.foo().call(obj2) // -> 3 obj2.foo().call(obj1) // -> 2// 可以看到,顯式綁定優(yōu)先級高于隱式綁定

    2、隱式綁定與new綁定誰的優(yōu)先級更高?

    function foo(something) {this.a = something } const obj1 = {foo: foo } const obj2 = {}obj1.foo(2) console.log(obj1.a) // -> 2obj1.foo.call(obj2, 3) console.log(obj2.a) // -> 3const bar = new obj1.foo(4) console.log(obj1.a) // -> 2 console.log(bar.a) // -> 4// 可以看到,new綁定的優(yōu)先級高于隱式綁定

    3、new綁定與顯式綁定誰的優(yōu)先級更高?
    new和call/apply無法一起使用,因此無法通過 new foo.call(obj1)來直接進行測試,但是我們可以使用硬綁定來進行測試

    function foo(something) {this.a = something } const obj1 = {} const bar = foo.bind(obj1) bar(2) console.log(obj1.a) // -> 2const baz = new bar(3) console.log(obj1.a) // -> 2 console.log(baz.a) // -> 3// 可以看到,new綁定的優(yōu)先級高于顯式綁定

    四、判斷this步驟

    現(xiàn)在我們可以根據(jù)優(yōu)先級來判斷函數(shù)在某個調(diào)用位置引用的式哪條規(guī)則:

  • 函數(shù)是否在new中調(diào)用(new)綁定?如果是的話this綁定的是新創(chuàng)刊的對象。
    const bar = new foo()
  • 函數(shù)是否通過call,apply(顯示綁定)或者bind(硬綁定)調(diào)用?如果是的話,this綁定的式指定對象。
    const bar = foo.call(obj2)
  • 函數(shù)是否在某個上下文對象中調(diào)用(隱士綁定)?如果是的話,this綁定的是那個上下文對象
    const bar = obj1.foo()
  • 如果都不是的話,使用默認綁定。如果在嚴格式模式下,就綁定到undefined,否則綁定到全局對象
    const bar = foo()
  • 總結(jié)

    以上是生活随笔為你收集整理的this全面解析, 如何定位this指向,一文总结,再也不怕面试官追问啦的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。