javascript 之 this 用法

參考視頻:http://www.imooc.com/video/6430node

JavaScript中的this比較靈活,也是讓不少初學者摸不到頭腦,那麼根據在不一樣的環境下,在同一個函數,不一樣的調用方式下,那麼這個this也有多是不一樣的。windows

咱們先來看,全局做用於下的this。數組

全局的this(瀏覽器)瀏覽器

console.log(this.document===documet);//trueapp

console.log(this===window);//trueide

this.a=37;函數

console.log(window.a);//37this

全局做用域下的this通常指的是全局對象,在瀏覽器裏面通常指的是windows。好比上面的this.document就是window.document. 這裏的this就至關於window,因此this=window.spa

so,this.a=window.a。prototype

 

通常函數的this(瀏覽器)

function f1(){

return this;

}

f1()===window;//true,global object

好比咱們用這樣的通常函數聲明和通常表達式,而後咱們直接去調用這樣的函數的話,那麼這裏面的this仍然指向全局變量,那麼在瀏覽器裏面就是window,那麼在node.js裏面呢,就是global對象。

function f2(){

"use strict"//ee strict mode

return this;

}

f2()===undefined;//true

咱們須要注意的一點就是嚴格模式下呢,通常函數調用的this會指向這個undefined.

 

咱們更常見的做爲對象方法的函數的this:

var o={

prop:37,

f:function(){

return this.prop;

}

};

console.log(o.f());//logs 37

是將this做爲對象方法去用的時候,咱們知道,函數呢,若是做爲一個對象的屬性,好比咱們這建立的自變量o,那麼o裏面有個屬性f,它的值是一個函數對象,那對於這樣一個把函數做爲一個對象屬性值的方式,咱們經常叫作一個對象的方法。那麼多爲對象方法去調用的時候,好比這裏的用o.f()去調用,這種狀況的this通常會指向這樣一個對象o,這裏咱們能夠看到o.f()調用之後會返回37,由於this指向了o,因此至關於o.prop,因此最終的結果是37。

 

var o={prop:37};

function independent(){

return this.prop;

}

o.f=independent;

console.log(o.f());//logs 37

那麼這裏面,咱們不止是必定要定義成函數自變量的對象,好比這裏面咱們定義了一個對象o,只有一個屬性prop:37;那麼這裏面咱們有個獨立的independent函數,那麼這裏面的函數,咱們仍然return this.prop,若是我直接去調用independent的話,則this依舊指向window。這裏臨時建立一個o的屬性f(便是o.f)而且指向independent,因此這樣再調用console.log(o.f(),則又跟上一條函數同理!

這裏面是否是看函數是怎麼建立的,而是隻要將這個函數做爲對象的方法,就像這個o.f()去調用的話,那麼,這個this,就會指向這個o.prop。

對象原型鏈上的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

建立一個對象o裏面有屬性f,而且函數做爲屬性的值,咱們經過Object.create建立了一個對象p,而對象P是一個空對象,而且它的原型指向了o,那麼p.a=1;p.b=4;這樣建立了對象的屬性,那麼我去調用它原型上方法的時候,this.a和this.b依舊能取到p.a和p.b的值。這裏面p的原型纔是o,也就是說,調用p.f()的時候調用的時候這個對象原型對象上的o上面的屬性f。

get/set方法與this:

function  modulus(){

return Math.aqrt(thisre*this.re+this*this.im);

}

var 0={

re:1,

im:-1,

get phase(){

return Math.atan2(this.im,this.re);

}

};

Object.defineProperty(o,'modules',{

get:modulus,enumerable,configurable:ture});

console.log(o.phase,o.modulus);//logs-0.78   14.4142

get/set方法也是相似的,這裏用的是一個modules。而後這裏咱們去計算this.re和this.im,這裏咱們用一個對象o,而且o裏面有一個get方法,給這樣的屬性phase,再用

Object.defineProperty(object, propertyname, descriptor)去定義o的屬性,這裏咱們一樣能夠調用o.phase和o.modulus去拿到o的屬性,那麼modules裏面的this依舊會指向o的re和im,咱們也要知道get/set方法裏面的this也是會指向它所在的那個對象裏面,那麼咱們臨時動態區別一下O這個對象與建立.modulus的屬性也是相似的,那麼這一點上,和通常的對象屬性做爲函數對象也是相似的! 

構造器中的this:
function MyClass(){
this.a=37;
}
var o= new MyClass();
console.log(o.a);//37

function C2(){
this.a=37;
return{a:38};
}
o=new C2();
console.log(o.a);//38
若是咱們正常去調用MyClass這個函數的話,this就是指向全局變量window,可是若是用new MyClass來把它做爲構造器去調用的話,那麼MyClass的this會指向空的對象,而且這個對象會指向原型MyClass.prototype.這裏使用了new之後,那麼這個this會指向一個原型爲MyClass.prototype屬性的這樣一個空對象,那麼這樣因爲咱們的this.a賦值了37,並且MyClass的返回值默認是this,因此這對象o就會輸出37。那麼相似的咱們定義了一個函數C2,而後this.a=37,可是return裏面的返回的語句是a:38,因此a就再也不是37了,而是38。當咱們使用new來建立這樣一個構造器來這樣去調用的時候,那麼這樣的this會指向一個原型爲MyClass.prototype這樣一個空對象,最後仍是要看返回值,若是你沒有寫return語句,則默認返回this,若是有return語句返回了一個對象的話,因此會將return的對象做爲返回值,因此o.a就是38.

call/apply方法與this:function add(c,d){return this.a+this.b+c+d;}var 0= {a:1,b:3};add.call(,o,5,7);//1+3+5+7=16add.apply(o,[10,20]);//1+3+10+20=34function bar(){console.log(Object,prototype.toString.call(this));}bar.call(7);//"[object Number]"除了不一樣的調用方式,每個函數對象也會有方法,能夠去修改函數執行時的裏面的this,比較常見的就是call/apply。好比我這裏面的函數聲明add,咱們用this.a和this.b,和參數c和d把這四個數相加起來。咱們是怎麼作的呢,咱們是定義一個變量o,裏面有兩個屬性a:1,b:3,而後經過這個對象的的call方法,把第一個參數接受那個關於this的對象,後面是5和7(也就是咱們想添加的參數),也就是c=5,d=7,最終的結果是就1+3+5+7=16。其實call和apply其實沒有什麼差異,只是call和apply傳參的方式不一樣,call是直接把參數變量傳輸進去的,而apply是將參數做爲數組的形式傳輸進去,因此apply的結果是也是1+3+10+20=34,。如今咱們來區分一下狀況下用到這個call和apply,好比說,咱們想調用Object,prototype.toString,可是咱們想指定某一個this的時候,來調用一些咱們沒法直接調用的一些方法,那麼咱們這裏去調用bar。call(7),這樣就能拿到內部的這樣一個標籤間接的字符串。bind方法與this:function f(){return this.a;}var g=f.bind({a:"test"});console.log(g());//testvar o={a:37,f:f,g:g};console.log(o.f(),o.g());//37 test除了call/apply還有bind方法,bind方法只能兼容IE9以上版本,咱們定義了一個函數對象f(),而後咱們經過bind的方法,定義了一個a的對象,並把參數值「test」傳進去,這樣咱們就獲得了一個g對象,咱們到下面調用輸出的時候,發現已經調用了test這個參數,這樣是採用了綁定一次,並重復去調用,仍然實現這種綁定的話,這樣會比咱們使用call/apply高效一點。咱們下面又定義了一個函數o,而後把a賦值爲37,而後f賦值了f(),g賦值了g(),而後咱們輸出的o.f(),o.g()是37,test.這裏比較特殊的就是咱們使用了bind方法,即便咱們使用了bind方法,並把新綁定方法做爲對象的屬性去調用,那麼這裏依舊會按照以前的綁定去走,因此也就返回這個test
相關文章
相關標籤/搜索