this指向的是當前函數的做用域(對象實例),有以下的例子node
const app = { name: 'xiaoming', log() { console.log(this.name); }, child() { return { name: 'b', log() { console.log(this.name); }, }; }, }; app.log(); // xiaoming app.child().log(); // b
不管是否在嚴格模式(‘use strict’)下,在全局執行環境中(在任何函數體外部)this 都指向全局對象。react
console.log(this === window); // true this.name = 'react'; console.log(name); // react console.log(window.name); // react
在函數內部,this的值取決於函數被調用的方式。數組
非嚴格模式下,this默認指向全局對象。閉包
function f() { return this; } // brower f() === window; // node f() === global;
嚴格模式下,this默認指向調用函數的對象實例。app
function f() { 'use strict' return this; } f() === undefined;
由於這裏的f()是直接調用的,而不是做爲對象的屬性或方法調用的,如window.f(),因此這裏的this爲undefined。
若是要想把 this 的值從一個環境傳到另外一個,就要用 call 或者apply 方法函數
var obj = {a: 'Custom'}; // 這個屬性是在global對象定義的。 var a = 'Global'; function whatsThis(arg) { return this.a; // this的值取決於函數的調用方式 } whatsThis(); // 'Global' whatsThis.call(obj); // 'Custom' whatsThis.apply(obj); // 'Custom'
在JavaScript定義的函數都繼承自Function,咱們能夠經過Function.prototype屬性裏的call或apply方法將 this 值綁定到調用中的特定對象。this
function add(c, d) { return this.a + this.b + c + d; } var o = {a: 1, b: 3}; // 第一個參數是做爲‘this’使用的對象 // 後續參數做爲參數傳遞給函數調用 add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 // 第一個參數也是做爲‘this’使用的對象 // 第二個參數是一個數組,數組裏的元素用做函數調用中的參數 add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
使用 call 和 apply 函數的時候要注意,若是傳遞給 this 的值不是一個對象,JavaScript 會嘗試使用內部 ToObject 操做將其轉換爲對象。所以,若是傳遞的值是一個原始值好比 7 或 ‘foo’,那麼就會使用相關構造函數將它轉換爲對象,因此原始值 7 會被轉換爲對象,像 new Number(7) 這樣,而字符串 ‘foo’ 轉化成 new String(‘foo’) 這樣,例如:spa
function bar() { console.log(Object.prototype.toString.call(this)); } //原始值 7 被隱式轉換爲對象 bar.call(7); // [object Number]
箭頭函數沒有本身的this指針。經過 call() 或 apply() 方法調用一個函數時,只能傳遞參數(不能綁定this)。在封閉的詞法環境中,箭頭函數的this和普通函數的this一致;在全局代碼裏,箭頭函數的this被設置爲全局對象。.net
var obj = { bar: function() { var x = (()=> this); return x; } } // 以obj爲對象來調用bar(),因此this綁定的是obj var fn = obj.bar(); console.log(fn() === obj); // true // 這裏並無調用bar(),只是引用bar賦給fn2 var fn2 = obj.bar; // 使用全局變量來調用bar(),因此這裏的this綁定全局 console.log(fn2()() == window);
當函數在對象中被調用時,this指向的是調用該函數的對象。prototype
const app = { name: 'xiaohong', f: function() { console.log(this.name); } }
f() 函數裏的this指向的是app對象。
this 的綁定只受最靠近的成員引用的影響。例如:
var o = {prop: 37}; function independent() { return this.prop; } o.f = independent; console.log(o.f()); // logs 37 o.b = {g: independent, prop: 42}; console.log(o.b.g()); // 42
事實證實,這與他是對象 o 的成員沒有多大關係,最靠近的引用纔是最重要的。
若是該方法存在於一個對象的原型鏈上,那麼this指向的是調用這個方法的對象,就像該方法在對象上同樣。
var o = { f: function() { return this.a + this.b; } }; var p = Object.create(o); p.a = 1; p.b = 4; console.log(p.f()); // 5
在這個例子中,對象p沒有屬於它本身的f屬性,它的f屬性繼承自它的原型。雖然在對 f 的查找過程當中,最終是在 o 中找到 f 屬性的,這並無關係;查找過程首先從 p.f 的引用開始,因此函數中的 this 指向p。也就是說,由於f是做爲p的方法調用的,因此它的this指向了p。
getter 與 setter 中的 this
用做 getter 或 setter 的函數都會把 this 綁定到設置或獲取屬性的對象。
bind(this)
ES5 引入了 Function.prototype.bind。調用f.bind(someObject)會建立一個與f具備相同函數體和做用域的函數,可是在這個新函數中,this將永久地被綁定到了bind的第一個參數,不管這個函數是如何被調用的。bind綁定的參數只生效一次
function f(){ return this.a; } var g = f.bind({a:"azerty"}); console.log(g()); // azerty var h = g.bind({a:'yoo'}); // bind只生效一次! console.log(h()); // azerty
傳入bind的第二個參數以及後面的,依照前後順序構成綁定函數的參數。
var foo = { x: 3 } var bar = function(){ console.log(this.x); } bar(); // undefined var boundFunc = bar.bind(foo); boundFunc(); // 3
有時候,咱們需要保持this的上下文,也就是在一個運行環境中,想要訪問到的this值。在何時需要這麼作呢?
比方說將一個對象的方法賦值給了一個全局變量,而後在全局變量中調用這種方法,那麼this值就再也不是原來的對象而是window對象了。可是咱們還須要依照對象的方法來調用。
又比方說一個方法中包括了閉包,閉包是沒法訪問到其外部函數的this對象的,因爲this對象是在調用方法的時候本身主動生成,內部函數在搜索這兩個變量的時候僅僅會搜索到其自身的活動對象。而不會沿着做用域鏈往外搜索,因此閉包訪問不到外部函數的this值。
在react中,常看到
export default class App extends Component { constructor(props) { super(props); this.foo = this.foo.bind(this); } foo() { // todo something } render() { return ( <View> <Button onPress={this.foo()}/> </View> ) } }
若是你傳遞一個函數名給一個變量,而後經過在變量後加括號’()'來調用這個方法,此時方法內部的this的指向就會丟失。這就會出現外部的foo方法內部的this會丟失指向。
爲了解決這個問題,咱們須要在實例化對象的時候,須要在構造函數中綁定this,使得不管事件處理函數如何傳遞,它的this的指向都是固定的,固定指向咱們所實例化的對象。原文連接:https://blog.csdn.net/u013003052/article/details/87894194