国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

講清楚之 javascript中的this

selfimpr / 352人閱讀

摘要:講清楚之中的這一節(jié)來(lái)探討。所以當(dāng)函數(shù)作為構(gòu)造函數(shù)調(diào)用,則函數(shù)內(nèi)部的綁定到該函數(shù)上。在通過(guò)構(gòu)造函數(shù)實(shí)例化對(duì)象時(shí),對(duì)象內(nèi)部的也同樣指向該實(shí)例對(duì)象。

講清楚之 javascript中的this

這一節(jié)來(lái)探討this。 在 javascript 中 this 也是一個(gè)神的存在,相對(duì)于 java 等語(yǔ)言在編譯階段確定,而在 javascript 中, this 是動(dòng)態(tài)綁定,也就是在運(yùn)行期綁定的。這導(dǎo)致了 javascript 中 this 的靈活性,而且對(duì)識(shí)別對(duì)象不同的調(diào)用場(chǎng)景下 this 指向帶來(lái)了一些困擾。

在全局環(huán)境中this指向window,即this === window。this 的靈活性主要體現(xiàn)在函數(shù)環(huán)境中,容易判定出錯(cuò)的也是函數(shù)環(huán)境下的 this 指向.

this 是函數(shù)內(nèi)部的可見(jiàn)屬性之一(另一個(gè)是 arguments), 在函數(shù)內(nèi)部我們可以直接使用this訪問(wèn)指定對(duì)象的屬性。那么指定對(duì)象是如何確定的?

下面就圍繞 this 的指向?qū)ο?/b>來(lái)梳理

this 是怎么確定的?

首先 this 是在函數(shù)被調(diào)用時(shí)確定的, 也就是在進(jìn)入函數(shù)后,函數(shù)內(nèi)表達(dá)式、語(yǔ)句執(zhí)行前的變量對(duì)象創(chuàng)建階段確定的。

而它指向什么取決于函數(shù)在哪里被調(diào)用(在什么對(duì)象上被調(diào)用).

一般情形需要關(guān)注函數(shù)在哪里被調(diào)用、被怎么調(diào)用.

下面主要分析函數(shù)在不同調(diào)用場(chǎng)景下this的指向.

當(dāng)函數(shù)作為方法被對(duì)象擁有并調(diào)用時(shí) this 指向該對(duì)象,否則 this 為 undefind
把標(biāo)題展開(kāi)描述就是: 當(dāng)函數(shù)調(diào)用時(shí)是被某一個(gè)對(duì)象所擁有,函數(shù)內(nèi)的this將綁定到該對(duì)象上。如果函數(shù)是獨(dú)立調(diào)用的,則函數(shù)內(nèi)部的 this 在嚴(yán)格模式下為 undefind, 在非嚴(yán)格模式下 this 會(huì)指向 window(node.js中指向global)。

根據(jù)上面的原則,我們首要判斷的是函數(shù)被誰(shuí)所擁有,舉幾個(gè)栗子更好理解:

栗子1:

let a = 1
function foo () {
    console.log(this.a)
}

foo() // 1

foo() 是在全局環(huán)境下獨(dú)立調(diào)用的,此時(shí)函數(shù) foo 被全局對(duì)象擁有(this 指向 window),所以this.a獲取的是 window 全局對(duì)象下面的 a.

栗子2:

var a = 1
var foo = function (){
    console.log(this.a)
}
var too = {
    a: 2,
    b: foo
}
var bar = too.b

foo() // 1
too.b() // 2
bar() // 1

函數(shù)執(zhí)行時(shí)確定 this 指向的大致邏輯:

foo() :

在全局對(duì)象 window 下調(diào)用,所以輸出1。

too.b():

對(duì)象 too 的屬性 b 指向函數(shù) foo,此時(shí)函數(shù) foo 是 對(duì)象 too 內(nèi)部的一個(gè)方法;

too.b()執(zhí)行時(shí),b 是被對(duì)象 too調(diào)用的,此時(shí)內(nèi)部的 this 指向 對(duì)象 too;

所以this.a獲取的是too.a,輸出2;

bar():

對(duì)象 too 的方法被賦值給 bar, 即此時(shí) bar 標(biāo)識(shí)符同 foo 標(biāo)識(shí)符一樣都指向同一個(gè)棧地址所代表的函數(shù)。

執(zhí)行bar()此時(shí)在全局對(duì)下 window 下調(diào)用,所以輸出1。

栗子3:

var a = 1
var foo = function () {
    console.log(this.a)
}
var too = function (fn) {
    var a = 2
    fn()
}
too(foo) // 1

too(foo) :這里函數(shù) foo 作為參數(shù)被傳遞到函數(shù) too的內(nèi)部執(zhí)行, fn()執(zhí)行時(shí)并沒(méi)有被其他對(duì)象顯示擁有,所以我們隱式的判定fn()是在全局對(duì)象 window 下面執(zhí)行的,所以輸出 1 。

這個(gè)栗子很容易搞錯(cuò)(我自己感覺(jué)每過(guò)一段時(shí)間再看還是會(huì)錯(cuò)o(︶︿︶)o),第一印象輸出的應(yīng)該是2,那是應(yīng)為把 this 與作用域鏈弄混淆了。始終要記住作用域鏈?zhǔn)窃谠创a編碼階段就確定了,而 this 是在函數(shù)運(yùn)行階段才確定,屬于執(zhí)行上下文的概念,是在運(yùn)行階段依據(jù) this所在函數(shù)被誰(shuí)調(diào)用來(lái)確定的。

我們?cè)賮?lái)把上面的栗子稍微修改一下

栗子4:

var a = 1
var foo = function () {
    console.log(this.a) // 輸出 1
    console.log(a) // 區(qū)別在這里, 輸出 1
}
var too = function (fn) {
    var a = 2
    fn()
}
too(foo) // 1, 1
表達(dá)式 - -
console.log(this.a) 基于上下文 this 表達(dá)式所屬 foo 函數(shù)在 too 函數(shù)內(nèi)調(diào)用時(shí) this 指向 window 1
console.log(a) 基于作用域鏈 全局上下文中的變量 a 在 foo 函數(shù)作用域鏈上 1

不知道你理解了沒(méi)有,這個(gè)栗子也體現(xiàn)了上下文作用域在進(jìn)行變量/屬性查找時(shí)的區(qū)別

栗子5:

let c = 1
let foo = {
    c: 2
}
let too = function () {
    console.log(this.c)
}
foo.a = {
    b: too,
    c: 3
}

foo.a.b() // 3

this的綁定只受最靠近的成員引用的影響。foo.a.b()函數(shù)b作為對(duì)象foo.a的方法被調(diào)用,所以此時(shí)的this綁定到foo.ab與對(duì)象foo的包含成員沒(méi)有多大關(guān)系,最靠近的對(duì)象才決定this的綁定。

最后console.log(this.c)取到的是foo.ac的值 3 .

栗子5:

let a = 1
let foo = {
    a: 2,
    msg: function () {
        console.log(`hi, ${this.a}`)
    }
}
let too = Object.create(foo)

too.msg() // hi, 2

上面用對(duì)象foo作為原型創(chuàng)建新對(duì)象too, 所以對(duì)象 too 繼承對(duì)象 foo 的所有屬性、方法。too.msg()執(zhí)行時(shí),msg 函數(shù)被 too 調(diào)用,此時(shí)this就指向?qū)ο?b>too, 所以console.log(hi, ${this.a})訪問(wèn)的是從對(duì)象foo繼承來(lái)的 a.

所以對(duì)于在對(duì)象原型鏈上某處定義的方法,同樣的概念也適用。如果該方法存在于一個(gè)對(duì)象的原型鏈上,那么對(duì)象實(shí)例的this指向的是調(diào)用這個(gè)方法的對(duì)象,通過(guò)this可以訪問(wèn)到原形鏈上的方法。

通過(guò)上面的幾個(gè)栗子驗(yàn)證了我們的總結(jié):

當(dāng)函數(shù)作為對(duì)象方法調(diào)用時(shí) this 指向該對(duì)象,作為函數(shù)獨(dú)立調(diào)用時(shí) this 指向全局對(duì)象 window (嚴(yán)格模式下 this 為 undefind )。

大部分時(shí)候依據(jù)上面的原則來(lái)判斷 this 的指向是沒(méi)有問(wèn)題,但是 this 還有以下幾種特殊場(chǎng)景需要注意。

當(dāng)函數(shù)作為構(gòu)造函數(shù)調(diào)用,此時(shí)函數(shù)內(nèi)部的 this 指向函數(shù)自身
函數(shù)也是對(duì)象

栗子:

function Foo (a) {
    this.a = a // 實(shí)例化后 this 指向 too
}
let too = new Foo(1)

我們知道函數(shù) this 在運(yùn)行期確定,而構(gòu)造函數(shù)實(shí)例化時(shí)在內(nèi)部其實(shí)是為我們創(chuàng)建了一個(gè)新的對(duì)象,通過(guò)一系列的操作后將 this 指向了這個(gè)新對(duì)象。

new操作符執(zhí)行時(shí)的邏輯推導(dǎo)如下:

創(chuàng)建一個(gè)新的空對(duì)象;

將構(gòu)造函數(shù)的 this 指向這個(gè)新對(duì)象;

將構(gòu)造函數(shù)的原形添加到新對(duì)象的原形鏈里,將屬性、方法掛載在新對(duì)象上;

返回這個(gè)新對(duì)象

返回的新對(duì)象就是我們實(shí)例化的對(duì)象。即, new 操作符調(diào)用構(gòu)造函數(shù)時(shí),this 是指向內(nèi)部創(chuàng)建的新對(duì)象,最后會(huì)將新創(chuàng)建的對(duì)象返回給實(shí)例變量。

所以當(dāng)函數(shù)作為構(gòu)造函數(shù)調(diào)用,則函數(shù)內(nèi)部的 this 綁定到該函數(shù)上。在通過(guò)構(gòu)造函數(shù)實(shí)例化對(duì)象時(shí),對(duì)象內(nèi)部的 this 也同樣指向該實(shí)例對(duì)象。

當(dāng)函數(shù)使用 cal、apply 方法調(diào)用執(zhí)行,此時(shí) this 指向 call、apply 方法傳入的對(duì)象
在 javascript 里函數(shù)也是對(duì)象。 所有函數(shù)都繼承于 Function 構(gòu)造函數(shù),而  call、apply 是 Function.prototype 原形的方法,所以函數(shù)都從原形的原形里繼承了 call、apply 方法。

call、apply 用于向函數(shù)注入 this 對(duì)象和變量(call 與 apply 的區(qū)別在于傳遞的參數(shù)不一樣,其他沒(méi)有區(qū)別)。

let a = 1
let too = {
    a: 2
}
function foo () {
    console.log(this.a)
}
foo.call(too) // 2

函數(shù) foo 里面的 this 此時(shí)指向call傳遞進(jìn)來(lái)的對(duì)象 too,所以this.a打印的是 2.

如果傳遞給 this 的值不是一個(gè)對(duì)象,JavaScript 會(huì)嘗試使用內(nèi)部 ToObject 操作將其轉(zhuǎn)換為對(duì)象。因此,如果傳遞的值是一個(gè)原始值比如 7"foo",那么就會(huì)使用相關(guān)構(gòu)造函數(shù)將它轉(zhuǎn)換為對(duì)象,所以原始值 7 會(huì)被轉(zhuǎn)換為對(duì)象: new Number(7) ,而字符串 "foo" 轉(zhuǎn)化成 new String("foo")

function bar() {
  console.log(this, Object.prototype.toString.call(this));
}

//原始值 7 被隱式轉(zhuǎn)換為對(duì)象
bar.call(7); // Number {[[PrimitiveValue]]: 7}__proto__: Number[[PrimitiveValue]]: 7 "[object Number]"

ECMAScript 5 引入了 Function.prototype.bind。當(dāng)函數(shù)調(diào)用f.bind(someObject)會(huì)創(chuàng)建一個(gè)與f具有相同函數(shù)體和作用域的函數(shù),但是在這個(gè)新函數(shù)中,this將永久地被綁定到了bind對(duì)象someObject

栗子:

let a = 1
let too1 = {
    a: 2
}
function foo () {
    console.log(this.a)
}
let bar = foo.bind(too1)
let bar2 = {
    a: 4,
    b: bar
}

bar() // 2
bar.call({a: 3}) // 2
bar2.b() // 2

當(dāng)foo 通過(guò)bind創(chuàng)建一個(gè)新函數(shù)時(shí),新函數(shù)的this強(qiáng)制綁定到了傳入的對(duì)象too1, 后續(xù)執(zhí)行中bar即使是作為對(duì)象方法調(diào)用還是使用 call、apply 都無(wú)法替換使用 bind 綁定的 this。

當(dāng)函數(shù)是以箭頭函數(shù)方式創(chuàng)建的,此時(shí)的 this 指向箭頭函數(shù)執(zhí)行時(shí)的宿主函數(shù)的上下文

栗子:

function foo () {
    let that = this
    let too = () => {
        console.log(this === that) // true
    }
    too()
}
foo()

too 為箭頭函數(shù),內(nèi)部的 this 被指向?yàn)樗麆?chuàng)建時(shí)的上下文,即 foo 的 this 。反過(guò)來(lái)說(shuō)就是箭頭函數(shù)沒(méi)有自己的上下文,他共享的是封閉詞法上下文。

注意這里提到的 “this 是動(dòng)態(tài)綁定,在運(yùn)行期綁定的” 主要是指進(jìn)入函數(shù)后,函數(shù)運(yùn)行前的上下文創(chuàng)建階段(預(yù)處理),此時(shí)函數(shù)內(nèi)的表達(dá)式、語(yǔ)句并沒(méi)有執(zhí)行。但這里都統(tǒng)稱為函數(shù)運(yùn)行期,詳細(xì)請(qǐng)關(guān)注變量對(duì)象一節(jié)的描述(^.^)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/95267.html

相關(guān)文章

  • 講清楚之執(zhí)行上下文

    摘要:棧底為全局上下文,棧頂為當(dāng)前正在執(zhí)行的上下文。位于棧頂?shù)纳舷挛膱?zhí)行完畢后會(huì)自動(dòng)出棧,依次向下直至所有上下文運(yùn)行完畢,最后瀏覽器關(guān)閉時(shí)全局上下文被銷毀。 講清楚之執(zhí)行上下文 標(biāo)簽 : javascript 什么是執(zhí)行上下文? 當(dāng) JavaScript 代碼執(zhí)行一段可執(zhí)行代碼時(shí),會(huì)創(chuàng)建對(duì)應(yīng)的上下文(execution context)并將該上下文壓入上下文棧(context stack...

    3fuyu 評(píng)論0 收藏0
  • 講清楚之 javascript 對(duì)象繼承

    摘要:中的繼承并不是明確規(guī)定的,而是通過(guò)模仿實(shí)現(xiàn)的。繼承中的繼承又稱模擬類繼承。將函數(shù)抽離到全局對(duì)象中,函數(shù)內(nèi)部直接通過(guò)作用域鏈查找函數(shù)。這種范式編程是基于作用域鏈,與前面講的繼承是基于原型鏈的本質(zhì)區(qū)別是屬性查找方式的不同。 這一節(jié)梳理對(duì)象的繼承。 我們主要使用繼承來(lái)實(shí)現(xiàn)代碼的抽象和代碼的復(fù)用,在應(yīng)用層實(shí)現(xiàn)功能的封裝。 javascript 的對(duì)象繼承方式真的是百花齊放,屬性繼承、原型繼承、...

    Jonathan Shieber 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<