this詳解:JAVASCRIPT中的this究竟是誰?

this詳解:JAVASCRIPT中的this究竟是誰?


語法

this


全局對象

在全局執行上下文(函數以外),this引用的是全局對象.
javascript

1
2
3
4
5
6
7
console.log(this.document === document); // true
 
// In web browsers, the window object is also the global object:
console.log(this === window); // true
 
this.a = 37;
console.log(window.a); // 37


函數

在函數裏面,this這個值,得看怎麼來調用這個函數
html

簡單的調用

1
2
3
4
5
function f1(){
  return this;
}
 
f1() === window; // global object


在這個例子中,this不是沒有被賦予任何值.沒有申明爲嚴格模式下,this必需要有一個值去賦予.默認狀況下就是指向的是全局對象.

1
2
3
4
5
6
function f2(){
  "use strict"; // see strict mode
  return this;
}
 
f2() === undefined;

嚴格模式下, this沒有被申明,則爲undefined.他也能夠是任何值,好比null或者42或者其餘.

做爲一個對象的方法

當一個函數做爲一個對象的方法去調用,this指向的是對象自己.
java

下面的例子中,當 o.f()被調用,函數裏面的this指向的是 o對象.
web

1
2
3
4
5
6
7
8
var o = {
  prop: 37,
  f: function() {
    return this.prop;
  }
};
 
console.log(o.f()); // logs 37

假如 o 對象只申明瞭一個屬性,其f方法在開始聲明時尚未被定義,而後經過o.f直接被賦值爲其餘方法,其最後的效果也是同樣的,只是定義的先後問題,this依然指向的是o這個對象:express

1
2
3
4
5
6
7
8
9
var o = {prop: 37};
 
function independent() {
  return this.prop;
}
 
o.f = independent;
 
console.log(o.f()); // logs 37

這個例子說明的是f函數的調用,是做爲o的成員方法來執行.瀏覽器

咱們繼續來看,若是咱們給o設定另一個成員屬性b賦予爲一個對象,看下面這個例子,這時候,this該指向的是誰呢? 前面已經說過,this指向的是對象自己,因此o.b做爲一個對象,一樣這個對象的this指向的是他本身o.b.app

1
2
o.b = {g: independent, prop: 42};
console.log(o.b.g()); // logs 42


對象原型鏈中的this

一樣的概念也使用對象原型鏈中
ide

1
2
3
4
5
6
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沒有本身的屬性.它繼承了o的屬性.因此這時候經過p來調用f方法,this指向的是p,這是對象原型模式.這裏就是javascript中的原型繼承模式.函數


this與getter和setter

再次,用相同的概念也適用於getter和setter.函數使用getter或者setter來綁定到對象的屬性.post

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function modulus(){
  return Math.sqrt(this.re * this.re + this.im * this.im);
}
 
var o = {
  re: 1,
  im: -1,
  get phase(){
    return Math.atan2(this.im, this.re);
  }
};
 
Object.defineProperty(o, 'modulus', {
    get: modulus, enumerable:true, configurable:true});
 
console.log(o.phase, o.modulus); // logs -0.78 1.4142


做爲一個構造函數

.當一個函數做爲一個構造函數使用(同構new來構造).this這時候指向的是函數構造出來的對象.

提示: 雖然默認構造函數返回對象引用,它也能夠返回其餘對象 .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * Constructors work like this:
 *
 * function MyConstructor(){
 *   // Actual function body code goes here. 
 *   // Create properties on |this| as
 *   // desired by assigning to them.  E.g.,
 *   this.fum = "nom";
 *   // et cetera...
 *
 *   // If the function has a return statement that
 *   // returns an object, that object will be the
 *   // result of the |new| expression.  Otherwise,
 *   // the result of the expression is the object
 *   // currently bound to |this|
 *   // (i.e., the common case most usually seen).
 * }
 */
 
function C(){
  this.a = 37;
}
 
var o = new C();
console.log(o.a); // logs 37
 
 
function C2(){
  this.a = 37;
  return {a:38};
}
 
o = new C2();
console.log(o.a); // logs 38

在最後的例子中(C2),由於一個對象在構造函數期間返回,這個新對象就會被丟棄.("this.a=37"; 其實沒什麼做用的代碼.可是他也不是徹底是死碼,由於他被執行了.可是沒有影響到外面的代碼執行.)

 

call 和 apply

一個函數在內部使用this,經過使用call或者apply方法將它的值綁定到一個特殊的對象.全部方法繼承Function.prototype.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function add(c, d){
  return this.a + this.b + c + d;
}
 
var o = {a:1, b:3};
 
// The first parameter is the object to use as
// 'this', subsequent parameters are passed as
// arguments in the function call
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
 
// The first parameter is the object to use as
// 'this', the second is an array whose
// members are used as the arguments in the function call
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

咱們來看下下面的這個列子.bar.call(7)這一行代碼,將第一個參數爲一個數值,則這時候的bar方法裏面的this是指向Number.到這裏,你能夠試試執行另外的一行代碼 new Number(10).toString(),看看效果.

1
2
3
4
5
function bar() {
  console.log(Object.prototype.toString.call(this));
}
 
bar.call(7); // [object Number]


bind方法

ECMAScript 5 介紹了 Function.prototype.bind. bind是建立了一個新函數而不是修改一個函數.新函數的行爲和原來函數的行爲同樣,但他的接收者是咱們給定的對象,而原有函數的接收者保持不變.

1
2
3
4
5
6
7
8
9
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


做爲DOM事件處理

當一個函數用在事件處理上.他的this將是指向這個元素的自己事件(使用addEventListener添加監聽器事件中,有些瀏覽器不遵照公約,有本身的一套作法.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// When called as a listener, turns the related element blue
function bluify(e){
  // Always true
  console.log(this === e.currentTarget);
  // true when currentTarget and target are the same object
  console.log(this === e.target);
  this.style.backgroundColor = '#A5D9F3';
}
 
// Get a list of every element in the document
var elements = document.getElementsByTagName('*');
 
// Add bluify as a click listener so when the
// element is clicked on, it turns blue
for(var i=0 ; i<elements.length ; i++){
  elements[i].addEventListener('click', bluify, false);
}


內聯事件處理

當代碼在元素上進行調用處理,this指向的是這個DOM元素.

1
2
3
<button onclick="alert(this.tagName.toLowerCase());">
  Show this
</button>

上面顯示的是這個按鈕. 記住只有這種方式,返回的是這個元素.

1
2
3
<button this}()));">
  Show inner this
</button>

在這個例子中,內部函數this沒有被設置,所以它返回的全局對象window.

相關文章
相關標籤/搜索