日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

JavaScript中this綁定詳解

瀏覽:12日期:2023-11-17 08:57:40

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

學習this的第一步就是明白this既不是指向函數自身也不指向函數的作用域。this實際上是在函數被調用時發生的綁定,它指向什么地方完全取決于函數在哪里被調用。

默認綁定

在 javascript 中 ,最常用的函數調用類型就是 獨立函數調用 ,因此可以把這條規則看作是無法應用其他規則時的默認規則。如果在調用函數的時候,函數不帶任何修飾,也就是“光禿禿”的調用,那就會應用 默認綁定規則

function sayLocation() { console.log(this.atWhere)}var atWhere = 'I am in global'sayLocation() // 默認綁定,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函數內部執行sayName函數,this指向的同樣是全局的對象}person()

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

這就是 默認綁定規則 ,它是 javascript 中最常見的一種函數調用模式,this的綁定規則也是四種綁定規則中最簡單的一種,就是 函數在哪個作用域被調用,this 就綁定在這個作用域上

默認綁定里的嚴格模式

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

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

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

隱式綁定

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

function say() { console.log(this.name)}var obj1 = { name: 'zxt', say: say}var obj2 = { name: 'zxt1', say: say}obj1.say() // zxtobj2.say() // zxt1

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

隱式綁定時丟失上下文

function say() { console.log(this.name)}var name = 'global'var obj = { name: 'inside', say: say}var alias = obj.say // 設置一個簡寫 (1) alias() // 函數調用 輸出'global' (2)

可以看到這里輸出的是”global“,為什么就和上例中不一樣,我們明明只是給obj.say換了個名字而已?

首先我們來看上面第(1)句代碼,由于在 javascript 中,函數是對象,對象之間是引用傳遞,而不是值傳遞。因此,第(1)句代碼只是alias = obj.say = say,也就是alias = say,obj.say只是起了一個橋梁的作用,alias最終引用的是say函數的地址,而與 obj 這個對象無關了。這就是所謂的”丟失上下文“。最終執行alias函數,只不過簡單的執行了say函數,輸出'global'。

顯式綁定

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

apply(obj,[arg1,arg2,arg3,...]被調用函數的參數以數組的形式給出

call(obj,arg1,arg2,arg3,...)被調用函數的參數依次給出

而bind函數執行后,返回的是一個新函數。下面以代碼說明。

// 不帶參數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) // obj1speak.call(obj2) // obj2

因此可以看出,apply,call的作用就是給函數綁定一個執行上下文,且是顯式綁定的。因此,函數內的this自然而然的綁定在了call或者apply所調用的對象上面。

// 帶參數function count(num1, num2) { console.log(this.a * num1 + num2)}var obj1 = { a: 2}var obj2 = { a: 3}count.call(obj1, 1, 2) // 4count.apply(obj1, [1, 2]) // 4count.call(obj2, 1, 2) // 5count.apply(obj2, [1, 2]) // 5

上面這個例子則說明了apply和call用法上的差異。

而bind函數,則返回一個綁定了指定的執行上下文的新函數。還是以上面這段代碼為例

// 帶參數function count(num1, num2) { console.log(this.a * num1 + num2)}var obj1 = { a: 2}var bound1 = count.bind(obj1) // 未指定參數bound1(1, 2) // 4var bound2 = count.bind(obj1, 1) // 指定了一個參數bound2(2) // 4 var bound3 = count.bind(obj1, 1, 2) // 指定了兩個參數bound3() //4var bound4 = count.bind(obj1, 1, 2, 3) // 指定了多余的參數,多余的參數會被忽略bound4() // 4

所以,bind方法只是返回了一個新的函數,這個函數內的this指定了執行上下文,而返回這個新函數可以接受參數。

new 綁定

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

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

上面這個例子中,首先定義了一個Person函數,既可以普通調用,也可以以構造函數的形式的調用。當普通調用時,則按照正常的函數執行,輸出一個字符串。 如果是通過一個new操作符,則構造了一個新的對象。那么,接下來我們再看看兩種調用方式,this分別綁定在了何處首先普通調用時,前面已經介紹過,此時應用默認綁定規則,this綁定在了全局對象上,此時全局對象上會分別增加name和age兩個屬性。當通過new操作符調用時,函數會返回一個對象,從輸出結果上來看this對象綁定在了這個返回的對象上。

因此,所謂的new綁定是指通過new操作符來調用函數時,會產生一個新對象,并且會把構造函數內的this綁定到這個對象上。

事實上,在javascript中,使用new來調用函數,會自動執行下面的操作。

創建一個全新的對象

這個新對象會被執行原型連接

這個新對象會綁定到函數調用的this

如果函數沒有返回其他對象,那么new表達式中的函數調用會自動返回這個新對象

四種綁定的優先級

上面講述了javascript中四種this綁定規則,這四種綁定規則基本上涵蓋了所有函數調用情況。但是如果同時應用了這四種規則中的兩種甚至更多,又該是怎么樣的一個情況,或者說這四種綁定的優先級順序又是怎么樣的。

首先,很容易理解, 默認綁定的優先級是最低的 。這是因為只有在無法應用其他this綁定規則的情況下,才會調用默認綁定。那隱式綁定和顯式綁定呢?還是上代碼吧,代碼可從來不會說謊。

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)

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

function foo(something) { this.a = something}var obj1 = {}var bar = foo.bind(obj1) // 返回一個新函數bar,這個新函數內的this指向了obj1 (1)bar(2) // this綁定在了Obj1上,所以obj1.a === 2console.log(obj1.a)var baz = new bar(3) // 調用new 操作符后,bar函數的this指向了返回的新實例baz (2)console.log(obj1.a)console.log(baz.a)

我們可以看到,在(1)處,bar函數內部的this原本指向的是obj1,但是在(2)處,由于經過了new操作符調用,bar函數內部的this卻重新指向了返回的實例,這就可以說明 new 綁定 的優先級是要高于 顯式綁定 的。

至此,四種綁定規則的優先級排序就已經得出了,分別是

new 綁定 > 顯式綁定 > 隱式綁定 > 默認綁定

箭頭函數中的this綁定

箭頭函數是ES6里一個重要的特性。

箭頭函數的this是根據外層的(函數或者全局)作用域來決定的。函數體內的this對象指的是定義時所在的對象,而不是之前介紹的調用時綁定的對象。舉一個例子

var a = 1var foo = () => { console.log(this.a) // 定義在全局對象中,因此this綁定在全局作用域}var obj = { a: 2}foo() // 1 ,在全局對象中調用foo.call(obj) // 1,顯示綁定,由obj對象來調用,但根本不影響結果

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

// 定義一個構造函數function Person(name,age) { this.name = name this.age = age this.speak = function (){console.log(this.name)// 普通函數(非箭頭函數),this綁定在調用時的作用域 } this.bornYear = () => {// 本文寫于2016年,因此new Date().getFullYear()得到的是2016// 箭頭函數,this綁定在實例內部console.log(new Date().getFullYear() - this.age)} }}var zxt = new Person('zxt',22)zxt.speak() // 'zxt'zxt.bornYear() // 1994// 到這里應該大家應該都沒什么問題var xiaoMing = { name: 'xiaoming', age: 18 // 小明永遠18歲}zxt.speak.call(xiaoMing)// 'xiaoming' this綁定的是xiaoMing這個對象zxt.bornYear.call(xiaoMing)// 1994 而不是 1998,這是因為this永遠綁定的是zxt這個實例

因此 ES6 的箭頭函數并不會使用四條標準的綁定規則,而是根據當前的詞法作用域來決定this,具體來說就是,箭頭函數會繼承 外層函數調用的this綁定 ,而無論外層函數的this綁定到哪里。

小結

以上就是javascript中所有this綁定的情況,在es6之前,前面所說的四種綁定規則可以涵蓋任何的函數調用情況,es6標準實施以后,對于函數的擴展新增了箭頭函數,與之前不同的是, 箭頭函數的作用域位于箭頭函數定義時所在的作用域

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

全文完

標簽: JavaScript
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
综合激情网...| 国产日产高清欧美一区二区三区| 婷婷亚洲成人| 日韩中文字幕91| 黄色成人91| 欧美特黄视频| 香蕉精品999视频一区二区| 日韩av首页| 日韩大片在线观看| 成人av三级| 欧美亚洲在线日韩| 日韩一区二区免费看| 美女黄网久久| 欧美日韩视频免费看| 国产精品s色| yellow在线观看网址| 久久夜夜操妹子| 亚洲二区三区不卡| 亚洲一区国产| 日韩**一区毛片| 久久国产精品免费一区二区三区| 国产亚洲精品精品国产亚洲综合| 久久国产欧美日韩精品| 欧美成人aaa| 日韩av福利| 不卡在线一区二区| 国产精品免费看| 国产欧美综合一区二区三区| 日韩av在线播放网址| 1024精品久久久久久久久| 六月婷婷一区| 国产激情久久| 久久精品主播| 亚洲精品进入| 国产精品99久久精品| 亚洲午夜黄色| 日本久久二区| 成人国产精品| 黄色亚洲大片免费在线观看| 欧美片网站免费| 日韩欧美网址| 免费人成精品欧美精品| 国产精品二区影院| 国产综合婷婷| 国产欧美另类| 红桃视频国产一区| 国产福利一区二区三区在线播放| 欧美精品日日操| 亚洲青青久久| av高清一区| 日本欧美在线| 亚洲国产成人精品女人| 国产精品视频一区二区三区综合 | 欧美日韩免费观看视频| 在线亚洲自拍| 中文字幕高清在线播放| 亚洲三级精品| 久久亚洲在线| 欧美成人一二区| 亚洲欧美视频| 精品丝袜在线| 国产精品一级| 9色国产精品| 日韩电影免费在线观看| 清纯唯美亚洲综合一区| 久久精品亚洲欧美日韩精品中文字幕| 日日摸夜夜添夜夜添国产精品| 精品一区二区男人吃奶| 蜜臀久久99精品久久久久宅男| 精品国产午夜肉伦伦影院| 日韩在线播放一区二区| 亚洲电影有码| 国产高清日韩| 国产探花一区| 亚洲小说春色综合另类电影| 亚洲国产影院| 高清不卡亚洲| 麻豆视频一区二区| 日本在线视频一区二区| 国产亚洲高清视频| 欧美成人久久| 亚洲午夜黄色| 久久精品高清| 亚洲91视频| 伊伊综合在线| 国产精品白丝久久av网站| 亚洲精品乱码久久久久久蜜桃麻豆| 久久久水蜜桃av免费网站| 精品视频国内| 精品视频在线观看网站| 久久精品二区亚洲w码| 国产日产一区| 日韩av在线免费观看不卡| 亚洲五月综合| 综合色一区二区| 综合亚洲视频| 亚洲精品一二三**| 亚洲精品自拍| 日本亚洲不卡| 日本少妇一区二区| 日韩va亚洲va欧美va久久| 久久高清免费观看| 日韩专区一卡二卡| 在线精品观看| 91福利精品在线观看| 日韩和欧美一区二区| 亚洲精品国模| 日韩精品国产欧美| 日韩av一级片| 久久精品国产99国产精品| 日韩成人免费| 欧美 日韩 国产精品免费观看| 99国产精品自拍| 日韩高清一区| 国产一区精品福利| 婷婷综合五月| 18国产精品| 91麻豆国产自产在线观看亚洲| 99精品综合| 日韩精品一级中文字幕精品视频免费观看 | 久久夜夜操妹子| 亚洲香蕉网站| 亚洲精一区二区三区| 欧美日本不卡高清| 精品久久视频| 伊人久久大香线蕉av超碰演员| 色综合视频一区二区三区日韩| 国产精品一区二区三区美女 | 日韩国产在线观看| 国产一区二区亚洲| 亚洲黑丝一区二区| 日本91福利区| caoporn视频在线| 蜜臀久久久99精品久久久久久| 你懂的亚洲视频| 五月天久久久| 国产欧美日韩在线观看视频| 久久精品国语| 欧美久久一区二区三区| 92国产精品| 日韩精品欧美精品| 欧美性感美女一区二区| 欧美日本久久| 久久国产亚洲精品| 国产免费av一区二区三区| 99精品视频在线| 欧美日韩91| 国产综合色产| 国语对白精品一区二区| 亚洲免费婷婷| 亚洲成人av观看| 欧美国产三级| 综合国产精品| 国产在线日韩| 在线看片福利| 国产精品17p| 日韩在线网址| 国产亚洲一区在线| 福利片在线一区二区| 视频精品一区| 在线亚洲欧美| 亚洲成人精品| 红杏一区二区三区| 日韩成人午夜精品| 亚洲欧美日本视频在线观看| 日韩中文在线电影| 免费亚洲一区| 国产日韩一区| 日韩精品免费一区二区夜夜嗨| 一区三区视频| 亚洲高清二区| 天堂av在线| 久久伊人国产| 日本不卡在线视频| 亚洲三级国产| 亚洲日本国产| 日韩中文字幕亚洲一区二区va在线| 91看片一区| 风间由美中文字幕在线看视频国产欧美 | 欧美在线看片| 中文字幕一区二区三区日韩精品 | 日韩网站在线| 久久国产毛片| 日韩伦理福利| 久久精品色播| 韩日一区二区| 精品日韩在线| 激情中国色综合| 久久一区国产| 久久免费精品| 国产精品原创| 欧美久久天堂| 欧美sss在线视频| 久久久9色精品国产一区二区三区| 91av亚洲| 国产一区欧美| 亚洲自拍另类| 亚洲精品观看| 国产精品jk白丝蜜臀av小说| 国产精品久久久免费|