JS 裏的 thishtml
- 在 function 內部被建立
- 指向調用時所在函數所綁定的對象(拗口)
- this 不能被賦值,但能夠被 call/apply 改變
function C(){ this.a = 37; } var o = new C(); console.log(o.a); // logs 37 function C2(){ this.a = 37; return {a:38}; } var b = new C2(); console.log(b.a); // logs 38
對象內部方法的this指向調用這些方法的對象:node
//1:this指向調用函數的對象 var o = { prop: 37, f: function() { return this.prop; } }; console.log(o.f()); //37 this指向o var a = o.f; console.log(a()): //undefined this指向a ,a中沒有定義prop var o = {prop: 37}; function independent() { return this.prop; } o.f = independent; console.log(o.f()); // logs 37 this指向o
//2:this指向離被調用函數最近的對象 var o = { prop: 37, f: function() { return this.prop; } }; function independent() { return this.prop; } o.b = { g: independent, prop: 42 }; console.log(o.b.g()); //42 this指向o.b
普通函數內部的this分兩種狀況,嚴格模式和非嚴格模式。es6
//非嚴格模式下,this 默認指向全局對象window function f1(){ return this; } f1() === window; // true //而嚴格模式下, this爲undefined function f2(){ "use strict"; // 這裏是嚴格模式 return this; } f2() === undefined; // true
前面提到 this 是 「指向調用時所在函數所綁定的對象」, 這句話拗口但絕對正確,沒有一個多餘的字。
全局環境中有不一樣的宿主對象,瀏覽器環境中是 window, node 環境中是 global。這裏重點說下瀏覽器環境中的 this。
瀏覽器環境中非函數內 this 指向 window瀏覽器
alert(window=== this) // true
所以你會看很不少開源 JS lib 這麼寫緩存
(function() { // ... })(this);
或這樣寫app
(function() { // ... }).call(this);
好比 underscore 和 requirejs,大意是把全局變量 window 傳入匿名函數內緩存起來,避免直接訪問。至於爲啥要緩存,這跟 JS 做用域鏈有關係,讀取越外層的標識符性能會越差。dom
瀏覽器中比較坑人,非函數內直接使用 var 聲明的變量默認爲全局變量,且默認掛在 window 上做爲屬性。函數
var andy = '劉德華' alert(andy === window.andy) // true alert(andy === this.andy) // true alert(window.andy === this.andy) // true
由於這個特性,有些筆試題如requirejs
var x = 10; function func() { alert(this.x) } var obj = { x: 20, fn: function() { alert(this.x) } } var fn = obj.fn func() // 10 fn() // 10
沒錯,最終輸出的都是全局的 10。永遠記住這一點:
判斷 this 指向誰,看執行時而非定義時,只要函數(function)沒有綁定在對象上調用,它的 this 就是 window。性能
當函數被當作監聽事件處理函數時, 其 this 指向觸發該事件的元素 (針對於addEventListener事件)
// 被調用時,將關聯的元素變成藍色 function bluify(e){ //在控制檯打印出所點擊元素 console.log(this); //阻止時間冒泡 e.stopPropagation(); //阻止元素的默認事件 e.preventDefault(); this.style.backgroundColor = '#A5D9F3'; } // 獲取文檔中的全部元素的列表 var elements = document.getElementsByTagName('*'); // 將bluify做爲元素的點擊監聽函數,當元素被點擊時,就會變成藍色 for(var i=0 ; i<elements.length ; i++){ elements[i].addEventListener('click', bluify, false);
內聯事件中的this指向分兩種狀況:
對於延時函數內部的回調函數的this指向全局對象window(固然咱們能夠經過bind方法改變其內部函數的this指向)
看下邊代碼及截圖
//默認狀況下代碼 function Person() { this.age = 0; setTimeout(function() { console.log(this); }, 3000); } var p = new Person();//3秒後返回 window 對象 ============================================== //經過bind綁定 function Person() { this.age = 0; setTimeout((function() { console.log(this); }).bind(this), 3000); } var p = new Person();//3秒後返回構造函數新生成的對象 Person{...}
當函數經過Function對象的原型中繼承的方法 call() 和 apply() 方法調用時, 其函數內部的this值可綁定到 call() & apply() 方法指定的第一個對象上, 若是第一個參數不是對象,JavaScript內部會嘗試將其轉換成對象而後指向它。
例子:
function add(c, d){ return this.a + this.b + c + d; } var o = {a:1, b:3}; add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34 function tt() { console.log(this); } // 返回對象見下圖(圖1) tt.call(5); // Number {[[PrimitiveValue]]: 5} tt.call('asd'); // String {0: "a", 1: "s", 2: "d", length: 3, [[PrimitiveValue]]: "asd"}
若是採用 OOP 方式寫 JS 代碼,無可避免的會用到 this,方法內會訪問類的內部屬性(字段),也可能會調用類的另外一個方法。當類的方法內又有一個 function 時,好比瀏覽器端開發常常碰見的給 DOM 元素添加事件,這時若是事件處理器(handler)中的想調用類的一個方法,此時 handler 內的 this 是 dom 元素而非類的當前對象。這個時候,須要把 this 暫存,開發者發揮着本身的聰明才智留下了幾種經典的命名** me, self, that, _this**。如
如:
通常會在每一個方法的第一句就把 this 暫存下來。
bind方法在ES5引入, 在Function的原型鏈上, Function.prototype.bind。經過bind方法綁定後, 函數將被永遠綁定在其第一個參數對象上, 而不管其在什麼狀況下被調用。
function f(){ return this.a; } var g = f.bind({a:"azerty"}); console.log(g()); // azerty var o = {a:37, f:f, g:g}; console.log(o.f(), o.g()); // 37, azerty
箭頭函數的一個重要特徵就是顛覆了上面的一句話,再貼一次
判斷 this 指向誰,看執行時而非定義時,只要函數(function)沒有綁定在對象上調用,它的 this 就是 window
是的,前面一直用這句話來判斷 this 的指向,在箭頭函數裏前面半句就失效了。箭頭函數的特徵就是,定義在哪,this 就指向那。即箭頭函數定義在一個對象裏,那箭頭函數裏的 this 就指向該對象。以下
var book = { author: 'John Resig', init: function() { document.onclick = ev => { alert(this.author) ; // 這裏的 this 不是 document 了 } } }; book.init()
對象 book 裏有一個屬性 author, 有一個 init 方法, 給 document 添加了一個點擊事件,若是是傳統的函數,咱們知道 this 指向應該是 document,但箭頭函數會指向當前對象 book。
箭頭函數讓 JS 迴歸天然和簡單,函數定義在哪它 this 就指向哪,定義在對象裏它指向該對象,定義在類的原型上,就指向該類的實例,望文知意這樣更容易理解。
做爲方法的箭頭函數this指向全局window對象,而普通函數則指向調用它的對象
原文參考:
http://www.javashuo.com/article/p-aloxbrqk-mm.html
http://www.cnblogs.com/dongcanliang/p/7054176.html