深入了解JavaScript中的this關鍵字指向
全局作用域的this
- 游覽器:非嚴格模式指向window,嚴格模式指向undefined
- Node環(huán)境:指向{}
- 把文件看作module -> 加載編譯 -> 放到一個函數(shù)中 -> 通過 apply({})/call({}) 執(zhí)行這個函數(shù)
調用方式不同,this指向不同
在大多情況下,this出現(xiàn)在函數(shù)中。this指向什么,跟函數(shù)定義的位置無關,跟函數(shù)調用方式有關(綁定規(guī)則相關)。
function foo(){ console.log(this); } var obj = { foo: foo } //不同的調用方式this的指向不同,不同的調用方式對應著不同的綁定規(guī)則 foo();//window obj.foo();//obj foo.call("123");//String{"abc"}
this的綁定規(guī)則
- 默認綁定:函數(shù)獨立調用方式,this指向全局對象
- 隱式綁定:通過對象調用方法,會隱式的將this指向當前對象
- 顯示綁定:通過函數(shù)的apply、call、bind方法改變函數(shù)中this的指向
- apply/call:會自動調用,第一個參數(shù)都是設置this的指向,apply第二個參數(shù)為數(shù)組,call后面?zhèn)魅霝閰?shù)列表。
- bind:不會自動調用,會返回一個已經綁定好this的函數(shù),傳參與call一樣
- new綁定 :通過new關鍵字調用函數(shù),new 函數(shù)()
- 創(chuàng)建一個全新的對象
- 這個新對象會被執(zhí)行prototype連接
- 執(zhí)行構造函數(shù)中的代碼,為新對象添加屬性(this綁定在這個步驟完成)
- 如果函數(shù)沒有返回其他對象,表達式會返回這個新對象
this綁定優(yōu)先級(權重)
- 示綁定(bind>call/apply) > 隱式綁定 > 默認綁定
function fn() { console.log(this); } fn.bind(123).apply(321);
- new 綁定 > 隱式綁定 > 默認綁定
- new 綁定 > 顯示綁定(通過bind綁定this的函數(shù),可以被new關鍵字改變this指向)
function Fn(){ console.log(this); } fn.bind("132"); var obj = new Fn();
- new關鍵字不能和call/apply一起使用,因為new會主動調用函數(shù),call/apply也會主動調用函數(shù),這樣會產生沖突報錯
綁定優(yōu)先級:new 綁定 > 顯示綁定 > 隱式綁定 > 默認綁定
this規(guī)則之外
忽略顯示綁定
apply/call/bind:當傳入null/undefined時,自動將this綁定成全局對象
function fn(){ console.log(this); } fn.apply(null); fn.apply(undefined);
間接函數(shù)引用
var obj1 = { foo: function(){ console.log(this); } } var obj2 = {} ;(obj2.bar = obj1.foo)()//括號中包含賦值表達式,屬于獨立函數(shù)調用,是默認綁定,指向window
箭頭函數(shù) 將頭函數(shù)不會綁定this,arguments屬性箭頭函數(shù)不能作為構造函數(shù)來使用(不能new對象) 簡寫
- 簡寫一:當參數(shù)只有一個,可以省略括號
- 簡寫二:當函數(shù)體只有一行,可以省略大括號,并且會將這一行代碼的返回值return
var nums = [0, 1, 2, 3, 4, 5]; var result = nums .filter(item => item % 2 === 0) .map(item => item * 10) .reduce((preVal, curVal) => preVal + curVal, 0); console.log(result);
- 簡寫三:如果只有一個行,且需要返回一個對象,那么要將對象用括號包裹。因為省略"{}“后,不知道將對象的”{}"如何解析
var foo = () => ({ name: "foo", age: 18 });//這樣解析時會將對象當作一個整體
箭頭函數(shù)的this綁定
箭頭函數(shù)不遵循this的四種標準規(guī)則,箭頭函數(shù)內部沒有綁定this,也不能通過call/apply/bind綁定this,箭頭函數(shù)的this指向根據(jù)外層作用域決定
var obj = { getData() { setTimeout(function () { console.log(this); }, 200); }, }; //setTimeout中的函數(shù)屬于獨立調用,所以指向的是window //如果想讓this指向obj對象,setTimeout中使用箭頭函數(shù) obj.getData();
this相關面試題
面試題一:
var name = "window"; var person = { name: "person", sayName: function () { console.log(this.name); } }; function sayName() { var sss = person.sayName; sss(); person.sayName(); (person.sayName)(); (b = person.sayName)(); //包含賦值表達式,屬于間接函數(shù)引用 } sayName();
答案:window(默認綁定)、person(隱式綁定)、person(隱式綁定)、window(間接函數(shù)引用)
面試題二:
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.foo1.call(person2); person1.foo2(); person1.foo2.call(person2); person1.foo3()(); person1.foo3.call(person2)(); person1.foo3().call(person2); person1.foo4()(); person1.foo4.call(person2)(); person1.foo4().call(person2);
答案解析:
person1.foo1(); //person1:隱式綁定 person1.foo1.call(person2); //person2:顯示綁定 person1.foo2();//window:箭頭函數(shù)的this指向上層作用域的this person1.foo2.call(person2);//window:箭頭函數(shù)的this指向上層作用域的this,且不能改變箭頭函數(shù)指向 person1.foo3()();//window:先執(zhí)行person1.foo3(),然后拿到返回的函數(shù)再調用,屬于獨立調用,所以指向window person1.foo3.call(person2)();//window:先執(zhí)行person1.foo3.call(person2),拿到返回的函數(shù)再調用,屬于獨立調用 person1.foo3().call(person2);//person2:先執(zhí)行person1.foo3(),拿到返回的函數(shù)通過call調用this指向了person2 person1.foo4()(); //person1:拿到返回的箭頭函數(shù)后,箭頭函數(shù)沒有this,根據(jù)上層作用域決定,上層foo4函數(shù)指向的是person1對象(foo4是被person1直接調用的),所以內部箭頭函數(shù)也指向peroson1 person1.foo4.call(person2)(); //person2:給foo4綁定this為person2,箭頭函數(shù)調用this指向上層作用域,上層foo4的this被顯示綁定為了person2,那么內部的箭頭函數(shù)也是指向person2 person1.foo4().call(person2); //person1:call調用箭頭函數(shù),依然去上一層找,所以依然是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.foo1.call(person2) person1.foo2() person1.foo2.call(person2) person1.foo3()() person1.foo3.call(person2)() person1.foo3().call(person2) person1.foo4()() person1.foo4.call(person2)() person1.foo4().call(person2)
答案與解析:
person1.foo1() //person1 person1.foo1.call(person2) //person2 person1.foo2() //person1:箭頭函數(shù),指向上層作用域的this,上層作用域是“Person構造函數(shù)” person1.foo2.call(person2) //person1::箭頭函數(shù),指向上層作用域的this,不能被顯示綁定 person1.foo3()() //window:拿到返回的函數(shù)后調用,屬于獨立調用 person1.foo3.call(person2)() //window:拿到返回的函數(shù)后調用,屬于獨立調用 person1.foo3().call(person2) //person2:通過call顯示綁定 person1.foo4()() //person1:返回的箭頭函數(shù)去上層作用域找,上層foo的this指向person1 person1.foo4.call(person2)()//person2:返回的箭頭函數(shù)去上層作用域找,上層this通過call指向了person2 person1.foo4().call(person2)//person1:箭頭函數(shù)的this不能被顯示綁定
面試題四:
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()() person1.obj.foo1.call(person2)() person1.obj.foo1().call(person2) person1.obj.foo2()() person1.obj.foo2.call(person2)() person1.obj.foo2().call(person2)
答案與解析:
person1.obj.foo1()() //window:獨立調用 person1.obj.foo1.call(person2)() //window:獨立調用 person1.obj.foo1().call(person2) //person2:call顯示綁定 person1.obj.foo2()() //obj:返回的是箭頭函數(shù),this由上層作用域foo2函數(shù)決定,foo2的this指向obj(foo2是被obj直接調用的),所以返回的箭頭函數(shù)this也是指向obj person1.obj.foo2.call(person2)()//person2:箭頭函數(shù)上層作用域this被call指向person2,所以箭頭函數(shù)也是指向person2 person1.obj.foo2().call(person2)//obj:箭頭函數(shù)this不能被顯示綁定
到此這篇關于深入了解JavaScript中的this關鍵字指向的文章就介紹到這了,更多相關JavaScript中的this內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
簡介JavaScript中setUTCSeconds()方法的使用
這篇文章主要介紹了簡介JavaScript中setUTCSeconds()方法的使用,是JS入門學習中的基礎知識,需要的朋友可以參考下2015-06-06js中一維數(shù)組和二位數(shù)組中的幾個問題示例說明
這篇文章主要介紹了js中一維數(shù)組和二位數(shù)組中的幾個問題,并給出對應的解決方法,需要的朋友可以參考下2014-07-07