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

資訊專欄INFORMATION COLUMN

JavaScript中this綁定詳解

yacheng / 1059人閱讀

摘要:綁定最后要講的一種綁定規(guī)則,是指通過操作符調(diào)用構(gòu)造函數(shù)時發(fā)生的綁定。因此,所謂的綁定是指通過操作符來調(diào)用函數(shù)時,會產(chǎn)生一個新對象,并且會把構(gòu)造函數(shù)內(nèi)的綁定到這個對象上。事實上,在中,使用來調(diào)用函數(shù),會自動執(zhí)行下面的操作。

轉(zhuǎn)載請注明出處 https://segmentfault.com/a/11...

this 可以說是 javascript 中最耐人尋味的一個特性,就像高中英語里各種時態(tài),比如被動時態(tài),過去時,現(xiàn)在時,過去進(jìn)行時一樣,無論弄錯過多少次,下一次依然可能弄錯。本文啟發(fā)于《你不知道的JavaScript上卷》,對 javasript 中的 this 進(jìn)行一個總結(jié)。

學(xué)習(xí) this 的第一步就是明白 this 既不是指向函數(shù)自身也不指向函數(shù)的作用域。this 實際上是在函數(shù)被調(diào)用時發(fā)生的綁定,它指向什么地方完全取決于函數(shù)在哪里被調(diào)用。

默認(rèn)綁定

在 javascript 中 ,最常用的函數(shù)調(diào)用類型就是獨立函數(shù)調(diào)用,因此可以把這條規(guī)則看作是無法應(yīng)用其他規(guī)則時的默認(rèn)規(guī)則。如果在調(diào)用函數(shù)的時候,函數(shù)不帶任何修飾,也就是“光禿禿”的調(diào)用,那就會應(yīng)用默認(rèn)綁定規(guī)則, 默認(rèn)綁定的指向的是全局作用域。

function sayLocation() {
    console.log(this.atWhere)
}

var atWhere = "I am in global"

sayLocation() // 默認(rèn)綁定,this綁定在全局對象,輸出 “I am in global”

再看一個例子

var name = "global"
function person() {
    console.log(this.name) //  (1) "global"
      person.name = "inside"
    function sayName() {
        console.log(this.name) // (2) "global"  不是 "inside"
    }
    sayName() // 在person函數(shù)內(nèi)部執(zhí)行sayName函數(shù),this指向的同樣是全局的對象
}
person()

在這個例子中,person 函數(shù)在全局作用域中被調(diào)用,因此第(1)句中的 this 就綁定在了全局對象上(在瀏覽器中是是window,在node中就是global),因此第(1)句自然輸出的是一個全局對象的 name 屬性,當(dāng)然就是"global"了。sayName函數(shù)在person函數(shù)內(nèi)調(diào)用,即使這樣第(2)句中的this指代的仍然是全局對象,即使 person 函數(shù)設(shè)置了 name 屬性。

這就是默認(rèn)綁定規(guī)則,它是 javascript 中最常見的一種函數(shù)調(diào)用模式,this 的綁定規(guī)則也是四種綁定規(guī)則中最簡單的一種,就是綁定在全局作用域上

默認(rèn)綁定里的嚴(yán)格模式

在 javascript 中,如果使用了嚴(yán)格模式,則 this 不能綁定到全局對象。還是以第一個例子,只不過這次加上了嚴(yán)格模式聲明

"use strict"
function sayLocation() {
    console.log(this.atWhere)
}
var atWhere = "I am in global"
sayLocation()
// Uncaught TypeError: Cannot read property "atWhere" of undefined

可以看出,在嚴(yán)格模式下,把 this 綁定到全局對象上時,實際上綁定的是 undefined ,因此上面這段代碼會報錯。

隱式綁定

當(dāng)函數(shù)在調(diào)用時,如果函數(shù)有所謂的“落腳點”,即有上下文對象時,隱式綁定規(guī)則會把函數(shù)中的 this 綁定到這個上下文對象。如果覺得上面這段話不夠直白的話,還是來看代碼。

function say() {
    console.log(this.name)
}
var obj1 = {
    name: "zxt",
    say: say
}

var obj2 = {
    name: "zxt1",
    say: say
}
obj1.say() // zxt
obj2.say() // zxt1

很簡單是不是。在上面這段代碼中,obj1 , obj2 就是所謂的 say 函數(shù)的落腳點,專業(yè)一點的說法就是上下文對象,當(dāng)給函數(shù)指定了這個上下文對象時,函數(shù)內(nèi)部的this 自然指向了這個上下文對象。這也是很常見的一種函數(shù)調(diào)用模式。

隱式綁定時丟失上下文
function say() {
    console.log(this.name)
}
var name = "global"
var obj = {
    name: "inside",
    say: say
}
var alias = obj.say // 設(shè)置一個簡寫   (1) 
alias() // 函數(shù)調(diào)用 輸出"global"  (2)

可以看到這里輸出的是 ”global“ ,為什么就和上例中不一樣,我們明明只是給 obj.say 換了個名字而已?
首先我們來看上面第(1)句代碼,由于在 javascript 中,函數(shù)是對象,對象之間是引用傳遞,而不是值傳遞。因此,第(1)句代碼只是 alias = obj.say = say ,也就是 alias = sayobj.say 只是起了一個橋梁的作用,alias 最終引用的是 say 函數(shù)的地址,而與 obj 這個對象無關(guān)了。這就是所謂的”丟失上下文“。最終執(zhí)行 alias 函數(shù),只不過簡單的執(zhí)行了say函數(shù),輸出"global"

顯式綁定

顯式綁定,顧名思義,顯示地將this綁定到一個上下文,javascript中,提供了三種顯式綁定的方法,apply,call,bindapplycall的用法基本相似,它們之間的區(qū)別是:

apply(obj,[arg1,arg2,arg3,...] 被調(diào)用函數(shù)的參數(shù)以數(shù)組的形式給出
call(obj,arg1,arg2,arg3,...) 被調(diào)用函數(shù)的參數(shù)依次給出

bind函數(shù)執(zhí)行后,返回的是一個新函數(shù)。下面以代碼說明。

// 不帶參數(shù)
function speak() {
    console.log(this.name)
}

var name = "global"
var obj1 = {
    name: "obj1"
}
var obj2 = {
    name: "obj2"
}

speak() // global 等價于speak.call(window)
speak.call(window)

speak.call(obj1) // obj1
speak.call(obj2) // obj2

因此可以看出,apply, call 的作用就是給函數(shù)綁定一個執(zhí)行上下文,且是顯式綁定的。因此,函數(shù)內(nèi)的this自然而然的綁定在了 call 或者 apply 所調(diào)用的對象上面。

// 帶參數(shù)
function count(num1, num2) {
    console.log(this.a * num1 + num2)
}

var obj1 = {
    a: 2
}
var obj2 = {
    a: 3
}

count.call(obj1, 1, 2) // 4
count.apply(obj1, [1, 2]) // 4

count.call(obj2, 1, 2) // 5
count.apply(obj2, [1, 2]) // 5

上面這個例子則說明了 applycall 用法上的差異。
bind 函數(shù),則返回一個綁定了指定的執(zhí)行上下文的新函數(shù)。還是以上面這段代碼為例

// 帶參數(shù)
function count(num1, num2) {
    console.log(this.a * num1 + num2)
}

var obj1 = {
    a: 2
}

var bound1 = count.bind(obj1) // 未指定參數(shù)
bound1(1, 2) // 4

var bound2 = count.bind(obj1, 1) // 指定了一個參數(shù)
bound2(2) // 4 

var bound3 = count.bind(obj1, 1, 2) // 指定了兩個參數(shù)
bound3() //4

var bound4 = count.bind(obj1, 1, 2, 3) // 指定了多余的參數(shù),多余的參數(shù)會被忽略
bound4() // 4

所以,bind 方法只是返回了一個新的函數(shù),這個函數(shù)內(nèi)的this指定了執(zhí)行上下文,而返回這個新函數(shù)可以接受參數(shù)。

new 綁定

最后要講的一種 this 綁定規(guī)則,是指通過 new 操作符調(diào)用構(gòu)造函數(shù)時發(fā)生的 this 綁定。首先要明確一點的是,在 javascript 中并沒有其他語言那樣的類的概念。構(gòu)造函數(shù)也僅僅是普通的函數(shù)而已,只不過構(gòu)造函數(shù)的函數(shù)名以大寫字母開頭,也只不過它可以通過 new 操作符調(diào)用而已.

function Person(name,age) {
    this.name = name
    this.age = age
    console.log("我也只不過是個普通函數(shù)")
}
Person("zxt",22) // "我也只不過是個普通函數(shù)"
console.log(name) // "zxt"
console.log(age) // 22

var zxt = new Person("zxt",22) // "我也只不過是個普通函數(shù)"
console.log(zxt.name) // "zxt"
console.log(zxt.age) // 22

上面這個例子中,首先定義了一個 Person 函數(shù),既可以普通調(diào)用,也可以以構(gòu)造函數(shù)的形式的調(diào)用。當(dāng)普通調(diào)用時,則按照正常的函數(shù)執(zhí)行,輸出一個字符串。 如果是通過一個new操作符,則構(gòu)造了一個新的對象。那么,接下來我們再看看兩種調(diào)用方式, this 分別綁定在了何處首先普通調(diào)用時,前面已經(jīng)介紹過,此時應(yīng)用默認(rèn)綁定規(guī)則,this綁定在了全局對象上,此時全局對象上會分別增加 nameage 兩個屬性。當(dāng)通過new操作符調(diào)用時,函數(shù)會返回一個對象,從輸出結(jié)果上來看 this 對象綁定在了這個返回的對象上。
因此,所謂的new綁定是指通過new操作符來調(diào)用函數(shù)時,會產(chǎn)生一個新對象,并且會把構(gòu)造函數(shù)內(nèi)的this綁定到這個對象上。
事實上,在javascript中,使用new來調(diào)用函數(shù),會自動執(zhí)行下面的操作。

創(chuàng)建一個全新的對象

這個新對象會被執(zhí)行原型連接

這個新對象會綁定到函數(shù)調(diào)用的this

如果函數(shù)沒有返回其他對象,那么new表達(dá)式中的函數(shù)調(diào)用會自動返回這個新對象

四種綁定的優(yōu)先級

上面講述了javascript中四種this綁定規(guī)則,這四種綁定規(guī)則基本上涵蓋了所有函數(shù)調(diào)用情況。但是如果同時應(yīng)用了這四種規(guī)則中的兩種甚至更多,又該是怎么樣的一個情況,或者說這四種綁定的優(yōu)先級順序又是怎么樣的。
首先,很容易理解,默認(rèn)綁定的優(yōu)先級是最低的。這是因為只有在無法應(yīng)用其他this綁定規(guī)則的情況下,才會調(diào)用默認(rèn)綁定。那隱式綁定和顯式綁定呢?還是上代碼吧,代碼可從來不會說謊。

function speak() {
    console.log(this.name)
}

var obj1 = {
    name: "obj1",
    speak: speak
}
var obj2 = {
    name: "obj2"
}

obj1.speak() // obj1 (1)
obj1.speak.call(obj2) // obj2 (2)

所以在上面代碼中,執(zhí)行了obj1.speak(),speak函數(shù)內(nèi)部的this指向了obj1,因此(1)處代碼輸出的當(dāng)然就是obj1,但是當(dāng)顯式綁定了speak函數(shù)內(nèi)的thisobj2上,輸出結(jié)果就變成了obj2,所有從這個結(jié)果可以看出顯式綁定的優(yōu)先級是要高于隱式綁定的。事實上我們可以這么理解obj1.speak.call(obj2)這行代碼,obj1.speak只是間接獲得了speak函數(shù)的引用,這就有點像前面所說的隱式綁定丟失了上下文。好,既然顯式綁定的優(yōu)先級要高于隱式綁定,那么接下來再來比較一下new 綁定和顯式綁定。

function foo(something) {
    this.a = something
}

var obj1 = {}
var bar = foo.bind(obj1)  // 返回一個新函數(shù)bar,這個新函數(shù)內(nèi)的this指向了obj1  (1)
bar(2) // this綁定在了Obj1上,所以obj1.a === 2
console.log(obj1.a)

var baz = new bar(3)  // 調(diào)用new 操作符后,bar函數(shù)的this指向了返回的新實例baz  (2)

console.log(obj1.a)
console.log(baz.a) 

我們可以看到,在(1)處,bar函數(shù)內(nèi)部的this原本指向的是obj1,但是在(2)處,由于經(jīng)過了new操作符調(diào)用,bar函數(shù)內(nèi)部的this卻重新指向了返回的實例,這就可以說明new 綁定的優(yōu)先級是要高于顯式綁定的。
至此,四種綁定規(guī)則的優(yōu)先級排序就已經(jīng)得出了,分別是

new 綁定 > 顯式綁定 > 隱式綁定 > 默認(rèn)綁定

箭頭函數(shù)中的this綁定

箭頭函數(shù)是ES6里一個重要的特性。
箭頭函數(shù)的this是根據(jù)外層的(函數(shù)或者全局)作用域來決定的。函數(shù)體內(nèi)的this對象指的是定義時所在的對象,而不是之前介紹的調(diào)用時綁定的對象。舉一個例子

var a = 1
var foo = () => {
    console.log(this.a) // 定義在全局對象中,因此this綁定在全局作用域
}

var obj = {
    a: 2
}
foo() // 1 ,在全局對象中調(diào)用
foo.call(obj) // 1,顯示綁定,由obj對象來調(diào)用,但根本不影響結(jié)果

從上面這個例子看出,箭頭函數(shù)的 this 強(qiáng)制性的綁定在了箭頭函數(shù)定義時所在的作用域,而且無法通過顯示綁定,如apply,call方法來修改。在來看下面這個例子

// 定義一個構(gòu)造函數(shù)
function Person(name,age) {
    this.name = name
    this.age = age 
    this.speak = function (){
        console.log(this.name)
        // 普通函數(shù)(非箭頭函數(shù)),this綁定在調(diào)用時的作用域
    }
    this.bornYear = () => {
        // 本文寫于2016年,因此new Date().getFullYear()得到的是2016
        // 箭頭函數(shù),this綁定在實例內(nèi)部
        console.log(new Date().getFullYear() - this.age)
        }
    }
}

var zxt = new Person("zxt",22)

zxt.speak() // "zxt"
zxt.bornYear() // 1994

// 到這里應(yīng)該大家應(yīng)該都沒什么問題

var xiaoMing = {
    name: "xiaoming",
    age: 18  // 小明永遠(yuǎn)18歲
}

zxt.speak.call(xiaoMing)
// "xiaoming" this綁定的是xiaoMing這個對象
zxt.bornYear.call(xiaoMing)
// 1994 而不是 1998,這是因為this永遠(yuǎn)綁定的是zxt這個實例

因此 ES6 的箭頭函數(shù)并不會使用四條標(biāo)準(zhǔn)的綁定規(guī)則,而是根據(jù)當(dāng)前的詞法作用域來決定 this ,具體來說就是,箭頭函數(shù)會繼承 外層函數(shù)調(diào)用的this綁定 ,而無論外層函數(shù)的this綁定到哪里。

小結(jié)

以上就是javascript中所有this綁定的情況,在es6之前,前面所說的四種綁定規(guī)則可以涵蓋任何的函數(shù)調(diào)用情況,es6標(biāo)準(zhǔn)實施以后,對于函數(shù)的擴(kuò)展新增了箭頭函數(shù),與之前不同的是,箭頭函數(shù)的作用域位于箭頭函數(shù)定義時所在的作用域

而對于之前的四種綁定規(guī)則來說,掌握每種規(guī)則的調(diào)用條件就能很好的理解this到底是綁定在了哪個作用域。

全文完

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

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/80637.html

相關(guān)文章

  • Javascriptthis對象詳解

    摘要:返回作為構(gòu)造器當(dāng)函數(shù)作為構(gòu)造器使用關(guān)鍵詞,它的綁定為新構(gòu)造的對象。注意當(dāng)然默認(rèn)的構(gòu)造器返回的對象為當(dāng)前調(diào)用對象,它能被當(dāng)前對象中的新對象所取代如果對象的返回值不是對象,那么仍指向當(dāng)前對象。 javascript this 基礎(chǔ) call apply Redirected from https://developer.mozilla.org/zh-CN/docs/Web/JavaS...

    glumes 評論0 收藏0
  • JavaScript系列之事件詳解

    摘要:響應(yīng)某個事件的函數(shù)就叫事件處理程序或事件偵聽器。為事件指定事件處理程序的方法主要有種。事件處理程序事件直接加在元素上。事件委托利用冒泡的原理,把事件加到父元素或祖先元素上,觸發(fā)執(zhí)行效果,解決事件處理程序過多問題。事件委托優(yōu)點提高性能。 JavaScript簡單入門可以看看我丑丑的Github博客JavaScript簡單入門 事件 JavaScript與HTML之間的交互是通過事件實現(xiàn)的...

    pakolagij 評論0 收藏0
  • JS的call、apply、bind方法詳解

    摘要:不能應(yīng)用下的等方法。首先我們可以通過給目標(biāo)函數(shù)指定作用域來簡單實現(xiàn)方法保存,即調(diào)用方法的目標(biāo)函數(shù)考慮到函數(shù)柯里化的情況,我們可以構(gòu)建一個更加健壯的這次的方法可以綁定對象,也支持在綁定的時候傳參。原因是,在中,多次是無效的。 bind 是返回對應(yīng)函數(shù),便于稍后調(diào)用;apply 、call 則是立即調(diào)用 。 apply、call 在 javascript 中,call 和 apply 都是...

    zombieda 評論0 收藏0
  • JS基礎(chǔ)篇--call、apply、bind方法詳解

    摘要:首先我們可以通過給目標(biāo)函數(shù)指定作用域來簡單實現(xiàn)方法保存,即調(diào)用方法的目標(biāo)函數(shù)考慮到函數(shù)柯里化的情況,我們可以構(gòu)建一個更加健壯的這次的方法可以綁定對象,也支持在綁定的時候傳參。原因是,在中,多次是無效的。而則會立即執(zhí)行函數(shù)。 bind 是返回對應(yīng)函數(shù),便于稍后調(diào)用;apply 、call 則是立即調(diào)用 。 apply、call 在 javascript 中,call 和 apply 都是...

    lastSeries 評論0 收藏0
  • JSthis詳解

    摘要:實際上并不存在什么構(gòu)造函數(shù),只存在對于函數(shù)的構(gòu)造調(diào)用發(fā)生構(gòu)造函數(shù)的調(diào)用時,會自動執(zhí)行下邊的操作創(chuàng)建一個全新的對象。說明綁定的優(yōu)先級高于硬綁定。 原文閱讀 ??js中的this是很容易讓人覺得困惑的地方,這篇文章打算說一下this綁定的幾種情況,相信可以解決大部分關(guān)于this的疑惑。 this是在運(yùn)行的時候綁定的,不是在編寫的時候綁定的,函數(shù)調(diào)用的方式不同,就可能使this所綁定的對象不...

    Mike617 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<