JavaScript面向對象編程——Function類型

Function類型

Function與函數

函數它只定義一次,但可能被執行或調用屢次 。
Function類型是JavaScript提供的引用類型之一,經過Function類型建立Function對象。
在JavaScript中,函數也是以對象的形式存在的。每一個函數都是一個Function對象。函數名,本質就是一個變量名,是指向某個Function對象的引用。數組

// 1.函數聲明方式
function fun(){
    console.log('this is function');
}
// 2.字面量方式
var fn = function(){
    console.log('this is function too');
}
// 判斷函數是否爲Function類型的
console.log(fun instanceof Function);// true
console.log(fn instanceof Function);// true
// JavaScript中全部的函數都是Function類型的對象

/*
    3.建立Function類型的對象 -> 是一個函數
      var 函數名 = new Function(參數,函數體);
      * 因爲函數的參數和函數體都是以字符串形式傳遞給Function的
  */
var f = new Function('a','console.log(a)');
f(100);// 以函數方式進行調用

Function類型

構造函數

在JavaScript中,函數除了能夠經過函數定義語句或字面量表達式兩種方式定義以外,還能夠經過Function類型進行定義。(注意:經過Function類型定義函數的效率遠不如經過函數定義語句或字面量表達式兩種方式定義。目前,定義函數具備三種方式,這三種方式之間存在必定的差異。)閉包

// 1.Object與Function都是自身的類型
console.log(Object instanceof Object);// true
console.log(Function instanceof Function);// true
// 2.Object自身是構造函數,而構造函數也是函數,是函數都是Function類型
console.log(Object instanceof Function);// true
// 3.Function是引用類型,用於建立對象,是對象都是Object類型
console.log(Function instanceof Object);// true
// 變量的聲明提早
console.log(v);// undefined
var v = 100;
// 若是使用函數聲明方式定義函數時 -> 函數的聲明提早
fun();
function fun(){
    console.log('this is function');
}

apply()方法

Function的apply()方法用於調用一個函數,而且接受指定的this值,以及一個數組做爲參數。
語法結構:
1.thisArg參數:可選項,在func函數運行時使用this值。
2.argsArray參數:可選項,一個數組或者類數組對象,其中你那個的數組元素將做爲單獨的參數傳給func函數。也可使用argments對象做爲參數
3.返回值:調用該函數的返回結果。app

// 定義函數
function fun(value){
    console.log('this is ' + value);
}
// 函數的調用方式
fun('function');// 語法結構:函數名稱()

    apply(thisArg,argArray)方法 -> 用於調用一個指定函數
     參數
       thisArg - this
       argArray - 數組,做爲參數(實參)的列表
  
fun.apply(null, ['function']);

call()方法

Function的call()方法用於調用一個函數,而且接收指定的this值做爲參數,以及參數列表。
語法結構:
1.thisArg參數:在func函數運行時使用的this值。
2.arg1,arg2,...參數:指定的參數列表。
3.返回值:調用該函數的返回結果。
apply()與call()很是類似,不一樣之處在於提供參數的方式。函數

bind()方法

Function的bind()方法用於建立一個新的函數(稱之爲綁定函數),而且接收指定的this值做爲參數,以及參數列表。佈局

// 定義函數
function fun(value){
    console.log('this is ' + value);
}
/*
    bind(thisArg, arg1, arg2, ...)方法
    * 做用 - 用於建立一個新函數(稱爲綁定函數)
    * 參數
      * thisArg - this
       arg1, arg2, ... - 表示參數列表
    * 返回值 - 返回新的函數
 */
// var f = fun.bind();// 相對於從指定函數複製一份出來
// console.log(f);
// f();

fun('周芷若');// this is 周芷若

var f = fun.bind(null, '張無忌');
f();// this is 張無忌

沒有重載

在其餘開發語言中,函數具備一種特性,叫作重載。所謂的重載,就是定義多個同名的函數,但每個函數接收的參數的個數不一樣,程序會根據調用是傳遞的實參個數進行判斷,具體調用的是哪一個函數。this

// 定義函數
function fun(value){
    console.log('this is ' + value);
}

    bind(thisArg, arg1, arg2, ...)方法
     做用 - 用於建立一個新函數(稱爲綁定函數)
     參數
       thisArg - this
       arg1, arg2, ... - 表示參數列表
     返回值 - 返回新的函數
 
 var f = fun.bind();// 相對於從指定函數複製一份出來
 console.log(f);
 f();

fun('周芷若');// this is 周芷若

var f = fun.bind(null, '張無忌');
f();// this is 張無忌

但在JavaScript中函數時沒有重載現象的。也就是說,若是同時定義多個同名函數,只有最後一個定義的函數時有效的。
不過,JavaScript提供的arguments對象,該對象能夠模擬函數重載的現象。arguments對象是函數內部的本地變量;arguments已經再也不是函數的屬性了。
arguments對象能夠獲取函數的全部參數,但arguments對象並非一個數組,而是一個類數組對象(沒有數組特有的方法)。code

遞歸

在一個函數體內,若是想調用自身函數的話,有兩種方式;
1.經過使用自身函數實現
2.經過使用arguments對象的callee屬性實現。
調用自身的函數被稱之爲遞歸函數。在某種意義上,遞歸近似於循環。二者都重複執行相同的代碼,而且二者都須要一個終止條件以免無限循環或者無限遞歸。對象

/* 函數的遞歸 -> 就是在指定函數的函數體中調用自身函數
function fun(){
    // 當前函數的邏輯內容
    console.log('this is function');
    // 調用自身函數 -> 實現遞歸
    fun();
}
fun();
*/

function fn(v){
    console.log(v);
    if (v >= 10) {
        return;
    }
    // fn(v + 1);
    arguments.callee(v + 1);
}
fn(0);//致使出錯

var f = fn;
fn = null;
f(0);
// console.log(f);

特殊函數

匿名函數

JavaScript能夠將函數做爲數據使用。做爲函數本體,他就像普通的數據同樣,不必定要有名字。默認名字的函數被稱之爲匿名函數。
匿名函數的兩種用法:
1.能夠將匿名函數做爲從參數傳遞給其餘函數。這樣,接收函數就能利用所傳遞的函數來完成某些事請。
2.能夠定義某個匿名函數來執行某些一次性任務。遞歸

JavaScript語法中,定義函數必須定義函數名稱 -> 匿名函數
function (){
    console.log('this is function');
}


    匿名函數的做用:
    1.將匿名函數做爲參數傳遞給其餘函數 -> 回調函數
    2.將匿名函數用於執行一次性任務 -> 自調函數

回調函數

當一個函數做爲參數傳遞給另外一個函數時,做爲參數的函數被稱之爲回調函數。生命週期

// 做爲另外一個函數(fn)的參數的函數(one) -> 回調函數
var one = function(){
    return 1;
}

function fn(v){
    return v();
}
// one函數僅是做爲fn函數的參數出現 -> 並非調用
// var result = fn(one);
/*
    以上代碼等價於如下代碼
    如下代碼中做爲參數的函數 -> 匿名回調函數
  */
var result = fn(function(){return 1;});

console.log(result);// 1

自調函數

所謂自調函數就是在定義函數後自行調用。
1.第一對括號的做用,放置的是一個匿名函數。匿名函數接受一個參數
2.第二個對括號的做用,是‘當即調用’。在調用時,向匿名函數傳遞參數內內容。
自調函數只需將匿名函數的定義放進一對括號中,而後外面在跟一個對括號。

自調函數 - 定義即調用的函數
     第一個小括號 - 用於定義函數
     第二個小括號 - 用於調用函數
 
// 全局做用域 - 生命週期:JavaScript文件從執行到執行完畢
(function(value){
    // 函數做用域 - 生命週期:從函數調用到調用完畢
    console.log('this is ' + value);
})('function');
// 表達式語法
(function(value){
    // 函數做用域 - 生命週期:從函數調用到調用完畢
    console.log('this is ' + value);
}('function'));

!function(value){
    // 函數做用域 - 生命週期:從函數調用到調用完畢
    console.log('this is ' + value);
}('function');

+function(value){
    // 函數做用域 - 生命週期:從函數調用到調用完畢
    console.log('this is ' + value);
}('function');

做爲值的函數

將一個函數做爲另外一個函數的結果進行返回,做爲結果返回的函數稱之爲做爲置的函數。

var one = function(){
    return 100;
}
// 做爲值的函數 -> 內部函數的一種特殊用法
function fun(){
    var v = 100;
    // 內部函數
    return function(){
        return v;
    };
}

var result = fun();
// console.log(result);// one函數
// console.log(result());// 100

console.log(fun()());

閉包

做用域鏈

不少開發語言中都具備塊級做用域,但ECMAScript5版本中並無跨級做用域,這常常會致使理解上的困惑。
雖然ECMAScript5版本沒有塊級做用域,但具備函數做用域。在某個函數內部定義的變量的做用域就是該函數做用域。
每一段JavaScript代碼(全局代碼或函數)都有一個與之關聯的做用域。這個做用域鏈是一個對象列表或鏈表,這組最想定義了這段代碼「做用域中」的變量。

var a = 10;// 全局變量
function fun(){
    var b = 100;// fun函數做用域的局部變量
    // 內部函數
    function fn(){
        var c = 200;// fn函數做用域的局部變量
        // 內部函數
        function f(){
            var d = 300;// f函數做用域的佈局變量
            // 調用變量
            console.log(a);// 10
            console.log(b);// 100
            console.log(c);// 200
            console.log(d);// 300
        }
        f();
        // 調用變量
        // console.log(a);// 10
        // console.log(b);// 100
        // console.log(c);// 200
        // console.log(d);// d is not defined
    }
    fn();
    // 調用變量
    // console.log(a);// 10
    // console.log(b);// 100
    // console.log(c);// c is not defined
    // console.log(d);// d is not defined
}
fun();

閉包是什麼

JavaScript容許函數嵌套,而且內部函數能夠訪問定義在外部函數中的全部變量和函數,以及外部函數能訪問的全部變量和函數。可是,外部函數卻不能訪問定義在內部函數中的變量和函數。
當內部函數以某種方式唄任何一個外部函數做用域訪問時,一個閉包就產生了。
閉包就是詞法表示包括沒必要計算的變量的函數,也就是說,該函數能使用函數外定義的變量。

var n;// 定義變量,但不初始化值
function fun(){// 函數做用域
    var v = 100;
    // 進行初始化值 -> 一個函數
    n = function(){
        console.log(v);
    }
    // n();
}
fun();

n();// 100

閉包的特色和做用特色:1.局部變量:在函數中定義有共享意義的局部變量。2.內部函數:在函數(f)中聲明內嵌函數,內嵌函數(g)對函數(f)中的局部變量進行訪問。3.外部使用:函數(f)向外返回此內嵌函數(g),外部能夠經過此內嵌函數持有並訪問聲明在函數(f)中的局部變量,而此變量在外部是經過其餘途徑沒法訪問的。做用1.提供可共享的局部變量。2.保護共享的局部變量。提供專門的讀寫變量的函數。3.避免全局污染。

相關文章
相關標籤/搜索