jaVa函數

函數是JavaScript世界裏的第一公民,換句話來講,就是咱們若是能夠精通JavaScript函數的使用,那麼對JavaScript的運用能夠更遊刃有餘了。熟悉JavaScript的人應該都知道,一樣的函數,以不一樣的方式調用的話,受影響最大的應該是 this 。下面咱們來講說JavaScript函數的各類調用模式。編程

 

1、普通函數的調用模式數組

 

  所謂普通函數的調用模式,也是JavaScript函數的最簡單的一種調用模式,直接就是函數名後接一個 () 實現調用,看下面代碼:app

 

function func(){函數

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

}this

func();prototype

  上面代碼,咱們用function關鍵字聲明瞭一個 func 函數,而且在函數體內打印 this===window,而後咱們直接調用函數func,咱們能夠看到控制檯是直接打印出 true ,也就是說,函數的這種普通調用模式,函數體內的 this 是指向全局環境 window 的。不清楚這點的同窗,能夠能會遇到這樣的一個bug:對象

 

複製代碼blog

var color = 'gg';ip

var obj = {

    color : 'red',

    show : function(){

        function func1(){

            console.log(this.color); //gg

        }

        func1();

    }

}

obj.show(); 

複製代碼

  咱們在全局環境下聲明瞭一個變量 color 和一個對象 obj ,在對象 obj 裏面咱們還聲明瞭一個 color 屬性 爲 'red',一個 show 方法。並且在 show 方法裏面呢,咱們還聲明瞭一個函數 func1 而且調用了 func1,func1 的做用是打印 this.color。最後咱們運行代碼 obj.show(); 調用obj裏面的show方法。不清楚函數的普通調用模式的特色的同窗可能會認爲此時在控制檯答應出來的會是 'red' 。實際上此時在控制檯答應出來的應該是 gg 。由於函數 func1 的調用模式是 普通函數調用模式(即便它是在 obj 的 show 方法裏面調用的),因此此時函數體內的 this 是指向 全局環境window 的,因此就打印了全局環境下的變量 color 。

 

  可能有些同窗會問:若是咱們但願 func1 函數打印出來的是 'red' 呢,應該怎麼改?其實很簡單,由於 obj.color 纔是 'red' ,因此咱們只須要把 指向 obj 的 this 引入到函數 func1 裏面就好了: 

 

複製代碼

var color = 'gg';

var obj = {

    color : 'red',

    show : function(){

        var that = this;

        function func1(){

            console.log(that.color); //red

        }

        func1();

    }

}

obj.show();

複製代碼

  在上面的代碼中,由於 show 裏面的 this 指向 obj 的,因此咱們在 show 裏面聲明一個變量 that = this;用來把指向 obj 的 this 引入到 func1 中,而後再把 func1 函數體內的 this.color 改成 that.color ,此時在控制檯打印出來的就是咱們想要的 'red' 了。

 

  可能如今又有同窗會問:爲何 show 裏面的 this 是指向 obj 的呢?這就是咱們要說的JavaScript函數的第二種調用模式:方法調用模式

 

2、方法調用模式

 

  方法調用模式,簡單來講就是把一個 JavaScript函數做爲一個對象的方法來調用,當一個函數被保存爲一個對象的屬性是,咱們就把它稱爲方法,例如上文的 obj 對象裏的 show ,當一個方法被調用時,函數體裏面的 this 就會綁定到這個對象,例如上文的 show 裏面的 this 。方法調用模式也很容易辨別:obj.show(),對象名 . 屬性名 () ;代碼的話能夠參考上文的 obj 代碼 ,博主就很少寫了。記住:方法的調用是能夠在函數體內經過 this 訪問本身所屬的那個對象的。

 

3、構造器調用模式

 

  博主認爲構造器調用模式是相對於其餘模式來講較爲複雜點的調用模式了。經過關鍵字 new 能夠把一個函數做爲構造器來調用。關鍵字 new 能夠改變函數的返回值:

 

複製代碼

function func2(name){

    this.name = name;

}

 

name; //undefined

 

//普通函數調用模式

var foo = func2('afei');

foo; //undefined

name; //afei

 

 

//構造器調用模式

var bar = new func2('lizefei');

bar.__proto__ === func2.prototype; //true

bar; //{name:'lizefei'}

bar.name; //'lizefei'

複製代碼

  在上示代碼中咱們聲明瞭一個函數 func2 ,分別用兩種不一樣的調用模式去調用它。由於函數 func2 並無顯式返回值,因此做爲普通函數去調用時,它什麼也沒有返回,因此 foo 的值是 undefined 。由於普通調用模式的 this 是指向 全局環境 window 的,因此 func2('afei'); 後,全局環境下就多了一個 name 變量且等於 'afei'。

 

  func2 做爲構造器調用時,咱們能夠看到,它返回的是一個對象,由於關鍵字 new 使得函數在調用是發生了以下的特殊變化:

 

  建立了一個新對象,並且這個新對象是連接到 func2 的 prototype 屬性的

  把函數裏的 this 指向了這個新對象

  若是沒有顯式的返回值,新對象做爲構造器func2的返回值進行返回(因此bar 是 {name:'lizefei'})

  這樣子咱們就能夠看出構造器的做用:經過函數的調用來初始化新建立出來的對象。在JavaScript的面向對象編程裏面,這個但是至關重要的。

 

  由於在函數的聲明上,在將來做爲構造器調用的函數和普通函數的聲明沒什麼區別,因此致使後來的開發者很容易由於調用模式的錯誤致使程序出問題。因此開發者們都默契地約定,用來作構造器調用的函數的函數名的第一個字符應該大寫,例如:Person,People。這樣子後來的開發者一看到函數名就知道要用構造器調用模式調用此函數了。

 

4、使用apply()和call()方法調用

 

  這種調用的模式是爲了更靈活控制函數運行的上下文環境而誕生的。簡單的說就是爲了靈活控制函數體內 this 的值。

 

  apply 和 call這兩個方法的第一個參數都是要傳遞被函數上下文的對象(簡單點說就是要綁定給函數 this 的對象)。其餘參數就有所不一樣了:

 

  apply方法的第二個參數是一個數組,數組裏面的值將做爲函數調用的參數;

 

  call方法,從第二個參數起(包括第二個參數),剩下的參數都是做爲函數調用的參數;

 

  讓咱們看看栗子:

 

複製代碼

var obj = {

    name :'afei'

}

function say(ag1,ag2){

    console.log(ag1+':'+ag2+" "+ this.name);

}

say.apply(obj,['apply方法','hello']); //apply方法:hello afei

say.call(obj,'call方法','hi'); //call方法:hi afei

複製代碼

  正如栗子所示,咱們把對象 obj 做爲函數 say 的上下文來調用函數 say ,因此函數裏的 this 是指向 對象 obj 的。在apply方法裏,咱們經過數組 ['apply方法','hello'] 給 say 方法傳遞了兩個參數('apply方法' 和 'hello'),因此打印出來是: apply方法:hello afei。

 

  同理 call 也是同樣,並且函數傳遞的方式經過上面的代碼也一目瞭然我,博主就很少作解釋了。

 

  另外,博主還據說apply和call這兩個方法除了傳遞參數的方式不同,執行的速度仍是apply 比 call 要快呢。不過博主就沒有實驗過。

 

5、總結

 

  在JavaScript裏面,函數只要的調用模式就是這幾種了(在ES6裏面還有一種很奇怪很特殊的函數調用模式,叫作’標籤模板‘,在這裏博主也很少說了,有空另更),只要掌握了這幾種主要的調用模式,那麼往後不再用擔憂 this 的值變來變去了。

 

  上文若是有漏的、有錯誤的地方,望各位小夥伴指出,小弟虛心向學。

 

ps:轉載請標明出處 http://www.cnblogs.com/afeihome/

 

分類: JavaScript

好文要頂 關注我 收藏該文    

阿飛22

關注 - 0

粉絲 - 0

+加關注

0 0

« 上一篇:Array.apply(null, {length: 20})和Array(20)的理解

posted @ 2017-07-03 16:38 阿飛22 閱讀(147) 評論(1) 編輯 收藏

評論列表

  回覆引用 #1樓 2017-07-03 16:57 最騷的就是你  

var color = 'gg';

var obj = {

color : 'red',

show : function(){

var func1=function(){

console.log(this.color); //red

}.bind(this);

func1();

}

}

obj.show();

相關文章
相關標籤/搜索