函數的四種調用方式

【轉】函數的四種調用方式

 

函數的四種調用模式

在 js 中 不管是函數, 仍是方法, 仍是事件, 仍是構造器, ... 其本質都是函數. 只是處在不一樣的位子而已.html

四種:數組

  1. 函數模式
  2. 方法模式
  3. 構造器模式
  4. 上下文模式

函數模式

特徵: 就是一個簡單的函數調用. 函數名的前面沒有任何引導內容.瀏覽器

function foo () {}
    var func = function () {};
    ...
    
    foo();
    func();
    (function (){})();

this 的含義: 在 函數中 this 表示全局對象, 在瀏覽器中是 windowmarkdown

方法模式

特徵: 方法必定是依附於一個對象, 將函數賦值給對象的一個屬性, 那麼就成爲了方法.app

function f() {
        this.method = function () {};
    }
    var o = {
        method: function () {} 
    }

this 的含義: 這個依附的對象.函數

構造器調用模式

建立對象的時候 構造函數作了什麼?post

因爲構造函數只是給 this 添加成員. 沒有作其餘事情. 而方法也能夠完成這個操做, 就 this 而言,
構造函數與方法沒有本質區別.this

特徵:url

  1. 使用 new 關鍵字, 來引導構造函數.
  2. 構造函數中發 this 與方法中同樣, 表示對象, 可是構造函數中的對象是剛剛建立出來的對象
  3. 構造函數中不須要 return, 就會默認的 return this

補充:prototype

  1. 若是手動的添加 return, 就至關於 return this
  2. 若是手動的添加 return 基本類型; 無效, 仍是保留原來 返回 this
  3. 若是手動添加 return null; 或 return undefiend, 無效
  4. 若是手動添加 return 對象類型; 那麼原來建立的 this 就會被丟掉, 返回的是 return 後面的對象

建立對象的模式

  1. 工廠方法

    // 工廠就是用來生產的, 所以若是函數建立對象並返回, 就稱該函數爲工廠函數
    function createPerson( name, age, gender ) {
        var o = {};
        o.name = name;
        o.age = age;
        o.gender = gender;
        return o;
    }
    
    // document.createElement()
  2. 構造方法
  3. 寄生式建立對象

    // 外表看起來就是構造方法, 可是本質不是的構造方法建立對象的方式
    function createPerson( name, age, gender ) {
        var o = {};
        o.name = name;
        o.age = age;
        o.gender = gender;
        return o;
    }
    var p = new createPerson( 'jim', 19, 'male' );
  4. 混合式建立

    上下文調用模型

上下文 就是環境, 就是自定義設置 this 的含義

語法:

  1. 函數名.apply( 對象, [ 參數 ] );
  2. 函數名.call( 對象, 參數 );

描述:

  1. 函數名就是表示的函數自己, 使用函數進行調用的時候默認 this 是全局變量
  2. 函數名也能夠是方法提供, 使用方法調用的時候, this 是指當前對象.
  3. 使用 apply 進行調用後, 不管是函數, 仍是方法都無效了. 咱們的 this, 由 apply 的第一個參數決定

注意:

  1. 若是函數或方法中沒有 this 的操做, 那麼不管什麼調用其實都同樣.
  2. 若是是函數調用 foo(), 那麼有點像 foo.apply( window ).
  3. 若是是方法調用 o.method(), 那麼有點像 o.method.apply( o ).

參數問題

不管是 call 仍是 apply 在沒有後面的參數的狀況下( 函數無參數, 方法無參數 ) 是徹底同樣的.

function foo() {
        console.log( this );
    }
    foo.apply( obj );
    foo.call( obj );

第一個參數的使用也是有規則的

  1. 若是傳入的是一個對象, 那麼就至關於設置該函數中的 this 爲參數
  2. 若是不傳入參數, 或傳入 null. undefiend 等, 那麼至關於 this 默認爲 window

    foo();
    foo.apply();
    foo.apply( null );
    foo.call( undefined );
  3. 若是傳入的是基本類型, 那麼 this 就是基本類型對應的包裝類型的引用
    • number -> Number
    • boolean -> Boolean
    • string -> String

除了 this 的參數外的參數

在使用 上下文調用的 時候, 原函數(方法)可能會帶有參數, 那麼這個參數在上下文調用中使用 第二個( 第 n 個 )參數來表示

function foo( num ) {
        console.log( num );
    }
    foo.apply( null, [ 123 ] );
    // 等價於
    foo( 123 );

應用

上下文調用只是能修改 this, 可是使用的最多的地方上是借用函數調用.

將僞數組轉換爲數組

傳統的作法

var a = {};
    a[ 0 ] = 'a'; 
    a[ 1 ] = 'b';
    a.length = 2;
    
    // 數組自帶的方法 concat
    // 語法: arr.concat( 1, 2, 3, [ 4, [ 5 ] ] );
    // 特色不修改原數組
    var arr = [];
    var newArr = arr.concat( a );

因爲 a 是僞數組, 只是長得像數組. 因此這裏不行, 可是 apply 方法有一個特性, 能夠將數組或僞數組做爲參數

foo.apply( obj, 僞數組 ); // IE8 不支持

將 a 做爲 apply 的第二個參數

var newArr = Array.prototype.concat.apply( [], a )

處理數組轉換, 實際上就是將元素一個一個的取出來構成一個新數組, 凡是涉及到該操做的方法理論上均可以

  1. push, unshift
  2. slice
  3. splice

push 方法

用法:  arr.push( 1 ); 將這個元素加到數組中, 並返回所加元素的個數
          arr.push( 1, 2, 3 ); 將這三個元素依次加到數組中, 返回所加個數
    
    var a = { length: 0 }; // 僞數組
    a[ a.length++ ] = 'abc'; // a[ 0 ] = 'abc'; a.length++;
    a[ a.length++ ] = 'def';
    
    // 使用一個空數組, 將元素一個個放到數組中便可
    var arr = [];
    arr.push( a ); // 此時不會將元素展開, 而是將這個僞數組做爲一個元素加到數組中
    // 再次利用 apply 能夠展開僞數組的特徵
    arr.push.apply( arr, a );
    // 利用 apply 能夠展開僞數組的特性, 這裏就至關於 arr.push( a[0], a[1] )

slice

語法: arr.slice( index, endIndex )
    若是第二個參數不傳, 那麼就是 從 index 一致獲取到結尾
    該方法不會修改原數組
    
    var a = { length: 0 };
    a[ a.length++ ] = 'abc';
    a[ a.length++ ] = 'def';
    
    // 假設他是一個數組, 就是應該 從 0 項開始截取到 最後
    // 若是能夠的話, 應該 a.slice( 0 )
    // 可是他沒有該方法
    // 借用 數組的 slice, 將 this 轉換成 這個僞數組
    
    var arr = [];
    var newArr = arr.slice.apply( a, [ 0 ] );
相關文章
相關標籤/搜索