JavaScript中?this?的綁定指向規(guī)則
問題來源
在 js
中,有一個(gè)疑惑的點(diǎn) this
, 它的指向問題,存在各種各樣的,來看一下,它是如何綁定指向的吧
- 函數(shù)在調(diào)用時(shí),
JavaScript
會(huì)默認(rèn)給 this 綁定一個(gè)值 this
的綁定和定義的位置(編寫的位置)沒有關(guān)系this
的綁定和調(diào)用方式以及調(diào)用的位置有關(guān)系this
是在運(yùn)行時(shí),動(dòng)態(tài)綁定的
this 綁定規(guī)則
1.默認(rèn)綁定
注意: 嚴(yán)格模式下默認(rèn)
this
為undefined
,非嚴(yán)格模式下才是window
作為獨(dú)立函數(shù)調(diào)用時(shí),采用的默認(rèn)綁定規(guī)則:
function foo() { console.log(this) // window } function test1() { console.log(this) // window test2() } function test2() { console.log(this) // window test3() } function test3() { console.log(this) // window } test1() function fn(fnc) { fnc() } var obj = { bar: function () { console.log(this) } } fn(obj.bar) // window 因?yàn)閌obj.bar`取出的是函數(shù),函數(shù)再被獨(dú)立執(zhí)行的
2.隱式綁定
作為對(duì)象方法調(diào)用時(shí),采用隱式綁定規(guī)則
function foo() { console.log(this) } var obj = { bar: foo } obj.bar() // obj var obj1 = { bar: foo } var obj2 = { obj1: obj1 } obj2.obj1.bar() // obj1 var obj3 = { foo: foo } var bar = obj1.foo // 取出函數(shù),獨(dú)立調(diào)用了 bar() // window
3.顯示綁定
使用 call、apply、bind
進(jìn)行綁定
function foo() { console.log(this) } // bind var obj = { name: 'jpliu' } var bar = foo.bind(obj) bar() // obj // call/apply foo.call(window) // window foo.call({ name: 'jpliu' }) // {name: 'jpliu'} foo.call(123) // Number對(duì)象的123 Number?{123} foo.apply('123') // String 對(duì)象的'123' String?{'123'}
4.new 綁定
通過 new
關(guān)鍵字實(shí)例化對(duì)象的時(shí)候,綁定為實(shí)例化的對(duì)象
function Person(name) { console.log(this) // Person {} this.name = name // Person { name: 'jpliu' } } var p = new Person('jpliu') console.log(p)
5.內(nèi)置方法
// 其實(shí)算是隱式綁定,因?yàn)檫@些方法都是 `window`的 window.setTimeout(function () { // 這里或許沒這么簡(jiǎn)單,這個(gè)是回調(diào)函數(shù),與隱式綁定,沒啥關(guān)系,這里是瀏覽器實(shí)現(xiàn)的黑盒 // 在 v8 中,有一個(gè)測(cè)試用例,模擬,是采用 call 綁定的,this是指向的 window // 所以這個(gè)看具體如何實(shí)現(xiàn) console.log(this) // window }, 2000) // 2.監(jiān)聽點(diǎn)擊 const boxDiv = document.querySelector('.box') // 隱式綁定 `boxDiv` 的`onclick` 方法觸發(fā) boxDiv.onclick = function () { console.log(this) } // `addEventListener`的`this`是隱式綁定 // 當(dāng)`callback`的`this`沒有顯示綁定時(shí) // 使用`bind`顯示綁定`addEventListener`的`this` boxDiv.addEventListener('click', function () { console.log(this) }) boxDiv.addEventListener('click', function () { console.log(this) }) boxDiv.addEventListener('click', function () { console.log(this) }) // 3.數(shù)組.forEach/map/filter/find // 可以通過第二個(gè)參數(shù)綁定回調(diào)函數(shù)的`this` var names = ['abc', 'cba', 'nba'] names.forEach(function (item) { console.log(item, this) }, 'abc') names.map(function (item) { console.log(item, this) }, 'cba')
6.規(guī)則優(yōu)先級(jí)
1.默認(rèn)規(guī)則的優(yōu)先級(jí)最低
2.顯示綁定優(yōu)先級(jí)高于隱式綁定
function foo() { console.log(this) } var obj = { name: 'obj', foo: foo.bind('aaa') } // [String: 'aaa'] obj.foo()
3.new 綁定優(yōu)先級(jí)高于隱式綁定
var obj = { name: 'obj', foo: function () { console.log(this) } } // new的優(yōu)先級(jí)高于隱式綁定 // foo {} var f = new obj.foo()
4.new 綁定優(yōu)先級(jí)高于 bind
- new 綁定和 call、apply 是不允許同時(shí)使用的,所以不存在誰的優(yōu)先級(jí)更高
- new 綁定可以和 bind 一起使用,new 綁定優(yōu)先級(jí)更高
function foo() { console.log(this) } var bar = foo.bind('aaa') // foo {} 不是 [String: 'aaa'] var obj = new bar()
7.規(guī)則之外
1.null 或者 undefined
// 非嚴(yán)格模式下 // apply/call/bind: 當(dāng)傳入null/undefined時(shí), 自動(dòng)將this綁定成全局對(duì)象 foo.apply(null) foo.apply(undefined) var bar = foo.bind(null) bar() // 嚴(yán)格模式下,就是 `null/undefined`
2.間接函數(shù)引用
var obj1 = { name: 'obj1', foo: function () { console.log(this) } } var obj2 = { name: 'obj2' } // 這里是取出了obj1.foo函數(shù),賦值給了obj2.bar // = 運(yùn)算法的返回值,就是右側(cè)的值, ob1.foo 的函數(shù)定義 // 相當(dāng)于取出函數(shù),然后獨(dú)立調(diào)用, 所以指向 window ;(obj2.bar = obj1.foo)()
3.箭頭函數(shù),箭頭函數(shù)是無法使用 bind/call/apply
綁定 this
的,箭頭函數(shù)的 this
是定義的時(shí)候所處的上下文環(huán)境,無法變更,屬于靜態(tài) this
, 而不是動(dòng)態(tài)綁定的
8.實(shí)踐
var name = 'window' var person = { name: 'person', sayName: function () { console.log(this.name) } } function sayName() { var sss = person.sayName sss() // window: 獨(dú)立函數(shù)調(diào)用 person.sayName() // person: 隱式調(diào)用 person.sayName() // person: 隱式調(diào)用 ;(b = person.sayName)() // window: 賦值表達(dá)式(獨(dú)立函數(shù)調(diào)用), 使用 = 號(hào)運(yùn)算符之后,返回了 person.sayName 這個(gè)函數(shù)方法,后續(xù)調(diào)用,跟 person 無關(guān) } sayName()
var name = 'window' var person1 = { name: 'person1', foo1: function () { console.log(this.name) }, foo2: () => console.log(this.name), foo3: function () { return function () { console.log(this.name) } }, foo4: function () { return () => { console.log(this.name) } } } var person2 = { name: 'person2' } // person1.foo1(); // person1(隱式綁定) // person1.foo1.call(person2); // person2(顯示綁定優(yōu)先級(jí)大于隱式綁定) // person1.foo2(); // window(不綁定作用域,上層作用域是全局) // person1.foo2.call(person2); // window // person1.foo3()(); // window(獨(dú)立函數(shù)調(diào)用) // person1.foo3.call(person2)(); // window(獨(dú)立函數(shù)調(diào)用) // person1.foo3().call(person2); // person2(最終調(diào)用返回函數(shù)式, 使用的是顯示綁定) // person1.foo4()(); // person1(箭頭函數(shù)不綁定this, 上層作用域this是person1) // person1.foo4.call(person2)(); // person2(上層作用域被顯示的綁定了一個(gè)person2) // person1.foo4().call(person2); // person1(上層找到person1)
var name = 'window' function Person(name) { this.name = name ;(this.foo1 = function () { console.log(this.name) }), (this.foo2 = () => console.log(this.name)), (this.foo3 = function () { return function () { console.log(this.name) } }), (this.foo4 = function () { return () => { console.log(this.name) } }) } var person1 = new Person('person1') var person2 = new Person('person2') person1.foo1() // person1 person1.foo1.call(person2) // person2(顯示高于隱式綁定) person1.foo2() // person1 (上層作用域中的this是person1) person1.foo2.call(person2) // person1 (上層作用域中的this是person1) person1.foo3()() // window(獨(dú)立函數(shù)調(diào)用) person1.foo3.call(person2)() // window person1.foo3().call(person2) // person2 person1.foo4()() // person1 person1.foo4.call(person2)() // person2 person1.foo4().call(person2) // person1
var name = 'window' function Person(name) { this.name = name this.obj = { name: 'obj', foo1: function () { return function () { console.log(this.name) } }, foo2: function () { return () => { console.log(this.name) } } } } var person1 = new Person('person1') var person2 = new Person('person2') person1.obj.foo1()() // window person1.obj.foo1.call(person2)() // window person1.obj.foo1().call(person2) // person2 person1.obj.foo2()() // obj person1.obj.foo2.call(person2)() // person2 person1.obj.foo2().call(person2) // obj
到此這篇關(guān)于JavaScript中 this 的綁定規(guī)則的文章就介紹到這了,更多相關(guān)JS this 綁定規(guī)則內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 一文全面解析JS中的this綁定規(guī)則
- JavaScript中this綁定規(guī)則你理解了嗎
- 細(xì)說JavaScript中的this指向與綁定規(guī)則
- JavaScript this綁定與this指向問題的解析
- JavaScript?中的?this?綁定規(guī)則詳解
- JavaScript中this的綁定你知道幾種?
- 詳解JavaScript中的this硬綁定
- 一文搞懂JavaScript中的this綁定規(guī)則
- 詳解JavaScript的this指向和綁定
- JavaScript this綁定過程深入詳解
- React.js綁定this的5種方法(小結(jié))
- JavaScript調(diào)用模式與this關(guān)鍵字綁定的關(guān)系
- 深入理解JavaScript this綁定規(guī)則
相關(guān)文章
JS實(shí)現(xiàn)響應(yīng)鼠標(biāo)點(diǎn)擊動(dòng)畫漸變彈出層效果代碼
這篇文章主要介紹了JS實(shí)現(xiàn)響應(yīng)鼠標(biāo)點(diǎn)擊動(dòng)畫漸變彈出層效果代碼,具有非常自然流暢的動(dòng)畫過度效果,涉及JavaScript針對(duì)鼠標(biāo)事件的響應(yīng)及頁面元素樣式的動(dòng)態(tài)操作相關(guān)技巧,需要的朋友可以參考下2016-03-03uniapp 如何設(shè)置 tabbar 的 midButton 按鈕
在UniApp開發(fā)中,設(shè)置TabBar的midButton按鈕可以增加用戶交互的便利性,本文介紹了在App.vue中監(jiān)聽事件的方法,并提供了官方文檔鏈接作為參考,通過這種方式可以實(shí)現(xiàn)TabBar中的特殊按鈕功能,提升應(yīng)用的用戶體驗(yàn)2024-10-10用javascript實(shí)現(xiàn)代替marquee的滾動(dòng)字幕效果代碼
用javascript實(shí)現(xiàn)代替marquee的滾動(dòng)字幕效果代碼...2007-10-10關(guān)于JavaScript 數(shù)組你應(yīng)該知道的事情(推薦)
這篇文章主要介紹了JavaScript 數(shù)組,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04el-select數(shù)據(jù)過多懶加載的解決(loadmore)
這篇文章主要介紹了el-select數(shù)據(jù)過多懶加載的解決(loadmore),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-05-05js隱式轉(zhuǎn)換的知識(shí)實(shí)例講解
在本篇文章中,小編給大家分享了關(guān)于js隱式轉(zhuǎn)換的相關(guān)知識(shí)點(diǎn)內(nèi)容,有興趣的朋友們參考學(xué)習(xí)下。2018-09-09JS實(shí)現(xiàn)課程表小程序(仿超級(jí)課程表)加入自定義背景功能
這篇文章主要介紹了JS實(shí)現(xiàn)課程表小程序(仿超級(jí)課程表)加入自定義背景功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-12-12