原文地址:JavaScript基礎心法——thisjavascript
歡迎star。html
若是有錯誤的地方歡迎指正。java
看看這個有着深不可測的魔力的this
究竟是個什麼玩意兒 ~git
在傳統面向對象的語言中,好比Java,this
關鍵字用來表示當前對象自己,或當前對象的一個實例,經過this
關鍵字能夠得到當前對象的屬性和調用方法。es6
在JavaScript中,this
彷佛表現地略有不一樣,這也是讓人「討厭」的地方~github
ECMAScript規範中這樣寫:瀏覽器
this 關鍵字執行爲當前執行環境的 ThisBinding。app
MDN上這樣寫:函數
In most cases, the value of this is determined by how a function is called.
在絕大多數狀況下,函數的調用方式決定了this的值。this
能夠這樣理解,在JavaScript中,this
的指向是調用時決定的,而不是建立時決定的,這就會致使this
的指向會讓人迷惑,簡單來講,this
具備運行期綁定的特性。
來看看不一樣的狀況五花八門的this
吧~
首先須要理解調用位置,調用位置就是函數在代碼中被調用的位置,而不是聲明的位置。
經過分析調用棧(到達當前執行位置所調用的全部函數)能夠找到調用位置。
function baz(){ console.log("baz"); bar(); } function bar(){ console.log("bar"); foo(); } function foo(){ console.log("foo"); } baz();
當咱們調用baz()
時,它會以此調用baz()
→bar()
→foo()
。
對於foo()
:調用位置是在bar()
中。
對於bar()
:調用位置是在baz()
中。
而對於baz()
:調用位置是全局做用域中。
能夠看出,調用位置應該是當前正在執行的函數的前一個調用中。
在全局執行上下文中this
都指代全局對象。
this
等價於window
對象var
=== this.
=== winodw.
console.log(window === this); // true var a = 1; this.b = 2; window.c = 3; console.log(a + b + c); // 6
在瀏覽器裏面this
等價於window
對象,若是你聲明一些全局變量,這些變量都會做爲this的屬性。
在函數內部,this
的值取決於函數被調用的方式。
this
指向全局變量。
function foo(){ return this; } console.log(foo() === window); // true
this
指向綁定的對象上。
var person = { name: "axuebin", age: 25 }; function say(job){ console.log(this.name+":"+this.age+" "+job); } say.call(person,"FE"); // axuebin:25 say.apply(person,["FE"]); // axuebin:25
能夠看到,定義了一個say
函數是用來輸出name
、age
和job
,其中自己沒有name
和age
屬性,咱們將這個函數綁定到person
這個對象上,輸出了本屬於person
的屬性,說明此時this
是指向對象person
的。
若是傳入一個原始值(字符串、布爾或數字類型)來當作this
的綁定對象, 這個原始值會被轉換成它的對象形式(new String()
),這一般被稱爲「裝箱」。
call
和apply
從this
的綁定角度上來講是同樣的,惟一不一樣的是它們的第二個參數。
this
將永久地被綁定到了bind
的第一個參數。
bind
和call
、apply
有些類似。
var person = { name: "axuebin", age: 25 }; function say(){ console.log(this.name+":"+this.age); } var f = say.bind(person); console.log(f());
全部的箭頭函數都沒有本身的this
,都指向外層。
關於箭頭函數的爭論一直都在,能夠看看下面的幾個連接:
MDN中對於箭頭函數這一部分是這樣描述的:
An arrow function does not create its own this, the this value of the enclosing execution context is used.
箭頭函數會捕獲其所在上下文的this值,做爲本身的this值。
function Person(name){ this.name = name; this.say = () => { var name = "xb"; return this.name; } } var person = new Person("axuebin"); console.log(person.say()); // axuebin
箭頭函數經常使用語回調函數中,例如定時器中:
function foo() { setTimeout(()=>{ console.log(this.a); },100) } var obj = { a: 2 } foo.call(obj);
附上MDN關於箭頭函數this
的解釋:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions#不綁定_this
this
指向調用函數的對象。
var person = { name: "axuebin", getName: function(){ return this.name; } } console.log(person.getName()); // axuebin
這裏有一個須要注意的地方。。。
var name = "xb"; var person = { name: "axuebin", getName: function(){ return this.name; } } var getName = person.getName; console.log(getName()); // xb
發現this
又指向全局變量了,這是爲何呢?
仍是那句話,this
的指向得看函數調用時。
this
被綁定到正在構造的新對象。
經過構造函數建立一個對象其實執行這樣幾個步驟:
因此this
就是指向建立的這個對象上。
function Person(name){ this.name = name; this.age = 25; this.say = function(){ console.log(this.name + ":" + this.age); } } var person = new Person("axuebin"); console.log(person.name); // axuebin person.say(); // axuebin:25
this
指向觸發事件的元素,也就是始事件處理程序所綁定到的DOM節點。
var ele = document.getElementById("id"); ele.addEventListener("click",function(e){ console.log(this); console.log(this === e.target); // true })
this
指向所在的DOM元素
<button onclick="console.log(this);">Click Me</button>
在許多狀況下JQuery的this
都指向DOM元素節點。
$(".btn").on("click",function(){ console.log(this); });
若是要判斷一個函數的this
綁定,就須要找到這個函數的直接調用位置。而後能夠順序按照下面四條規則來判斷this
的綁定對象:
new
調用:綁定到新建立的對象call
或apply
、bind
調用:綁定到指定的對象注意:箭頭函數不使用上面的綁定規則,根據外層做用域來決定this
,繼承外層函數調用的this
綁定。