初學javascript都會對js的this有許多迷惑例如如下的例子:
#var a = 'jack';var obj = {a: 'tom'##,##b: function(){ console.log(#this.a)#;}};var c = obj.b;c() ;//輸出jack
#剛接觸js#的人可能會用一些其他物件導向的語言來理解,覺得這裡輸出的應該是tom,但實際上這裡輸出的時jack , 但這是問什麼了?且樓主來一步步的分析.
在js中常見的this#的指向分為##4#種:1.
物件中的也就是物件的屬性是function, #而function#中存在對this的使用, #比如說如下範例:#
var obj = {a: 'tom' ,b: function(){ console.# console. log(this.a);}};obj.b();//輸出的是tom
#這種情況this指向的呼叫該函數的物件, 這裡就是obj , 再例如如下範例
:var obj = {a#: 'tom',b: function#(){ console.#log(this.a)##;},c: {c0: ##'rose',c1: function(){ console. log(this.c0##);} }};obj.##c# .c1();//輸出jack
# #函數呼叫時#包含多個對象,儘管這個函數是被最外層的物件所調用,this指向的也只是它上一級的物件
但是在開篇的例子中又是為什麼呢?
var a = 'jack'##;#var obj = {a#: 'tom', b: function#(){ console.#log (this.a)##;# }};var #c = obj.b ;c();//輸出
##大家要記住一句話this指向它最後呼叫它的物件,也就是這裡的# c雖然被賦予了obj.b的值,但是變數
window物件上,
###所以最後#####this### ###的指向是全域的######window######物件##########2. ###直接呼叫函數########### #也就直接使用宣告式或變數式宣告函數### , ###在全域中直接呼叫函數#######var name = 'tom';var a = function#(){##var name = 'jack';console.log##(##(this.name);}##;console.log(a())#;##//輸出# tom
這裡的a是在全域的window在宣告, 呼叫時也是等價於window.a()所以this的指向為全域的window物件,包含這種情況:
var name = 'tom';var ##a = function(){var name = 'jack';function b(){ console .log(this#.name);# }b();//輸出tom console.log(this#.name)##;};console.log(a());//輸出tom# a和b輸出的都是tom , 函數b 在函數a中隨後呼叫時卻還是指向全域的window物件##, 這是為什麼呢? 大家可以記住一句話, js中只要沒有物件直接呼叫函數, 函數呼叫時this的指向都會被指向到全域的window物件 像之前的範例呼叫時都是 , obect.function() , this的指向都會被指向到object上, 如 #var obj = {a: 'tom',#b: function (){ console.log(#this#.a);#}}##;obj.b();#//輸出##tom#像是開篇的例子用這句話也很好理解 函數#c的呼叫並沒有物件的呼叫所以會被指向到全域的window物件上 var a = 'jack';var obj = {a: 'tom',b : function##(){# console.#log(#(this.a);}#};var c = obj.b;c( );//輸出jack Js中的建構子跟普通函數沒有明顯的分割, 當任意一個普通函數用來建立一類物件時,它就被稱為建構函數,或建構器。一個函數要作為一個真正意義上的建構函數,需要滿足下列條件: 1、 在函數內部對新物件(this #)的屬性進行設置,通常是新增屬性和方法。 2、建構子可以包含回傳語句(不建議),但傳回值必須是this,或者其它非物件類型的值。 例如 function People(name, age, sex){this.name = name; this.age = age; #this.sex= sex;} var p = new People('tom',12,'#男##');console.log#(p.name # p.sex p.age); //輸出 tom男12 #這裡的this指向的就是目前被建立的對象 當然建構子也有特殊狀況, 例如#: # function People(name, age, sex){this.name = name; this.age = age; #this.sex= sex;return {};}var p = new People('tom',12, '男')##;console.log(p.name)#;##//輸出 #undefined this或非物件類型##, 所以這裡的People並不是嚴格意義上的建構子, 這裡宣告的p其實只是函數People的回傳值, 所以最後的輸出為undefined , 如果把這裡的回傳值改成非物件類型, 最後的結果就不一樣了 function People(name, age, sex){this.name = name; this.age = age; #this.sex= sex;return 1;}var p = new People('tom',12##,'男');console.log(p.name);##//輸出 tom 這裡的People就是嚴格意義上的建構子了, 所以 this還是指向目前被建立的物件 Call與apply函數其實實用法差不多, 第一個參數都是呼叫函數的物件, 後面的參數都是函數的參數, 只是call#函數的傳參方式為不限個數的傳參, 即call([thisObject[,arg1 [,arg2 [,...,argn]]]])後面的參數分別對應函數的呼叫的參數 , 而apply函數第一個參數和call的相同, 第二個參數為陣列類型, apply([thisObj [,argArray] ])陣列的每一個元素也分別對應函數呼叫的參數 , 當使用call或apply##函數是 , 方法中的this會被重新指向到call或apply函數的第一個參數, 例如: var a = 1#;var b = 2;var c = {a: 3,b#: 4##};function add(){ console.#log (this.a ##this#.b)}add();//輸出3add.#apply(c)##; //輸出7第一 呼叫時並沒有物件的直接呼叫所以會被指向到全域的window物件所以輸出結果為#3 , 而第一add 函數的呼叫是透過apply函數所以this的指向會被引導到c 所以最後的輸出結果為7Es6拓展 :# Es6中的箭頭函數的this指向與es5的##this有所不同, 我們這裡提一下: 由於箭頭函數不綁定this , 它會捕捉其所在(即定義的位置)上下文的 this值,作為自己的 this#一個值,所以call() / apply() / bind() 方法對箭頭函數來說只是傳入參數,對它的#this 毫無影響。考慮到 this 是詞法層面上的,嚴格模式中與 this 相關的規則都會被忽略。 物件中的箭頭函數 #var ##a = { name: 'tom',#b: {c : () => { console.log(this);} },}; b.c(); //輸出window物件中使用this會被指向到全域的 var test = function(){this.time #= 1##;#setTimeout(()=>{ console.##log#(this##(this.time);},# 100)};#var t = new test();#//輸出##1 #箭頭函數中沒有this指標指標, 所以指向只和他建立時所處的上下文環境有關, 這裡的是建構子的呼叫所以test#中this的指向為t物件, 所以箭頭函數中的this 本文介紹了Javascript中的this,更多相關內容請關注php中文網。 相關推薦:關於微信小程式上傳word、txt、Excel、PPT等檔案的詳解
# ######3. #在建構子中的this的指向
4. call或apply呼叫函數
以上是Javascript中的this的講解的詳細內容。更多資訊請關注PHP中文網其他相關文章!