JavaScript...Function類型...

Function類型

Function與函數

函數是這樣一段JavaScript代碼 它只定義一次 但可能被執行或調用屢次
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);// 以函數方式進行調用
  • Object與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');
}

Function類型

  • Function的apply()方法

Function的apply()方法用於調用一個函數 而且接受指定的this值 以及一個數組做爲參數緩存

// 定義函數
function fun(value){
    console.log('this is ' + value);
}
// 函數的調用方式
fun('function');// 語法結構:函數名稱()
/*
    apply(thisArg,argArray)方法 -> 用於調用一個指定函數
    * 參數
      * thisArg - this
      * argArray - 數組,做爲參數(實參)的列表
  */
fun.apply(null, ['function']);
  • Function的call()方法

Function的call()方法用於調用一個函數 而且接受指定的this值做爲參數 以及參數列表閉包

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

fun.apply(null,['function','張三']);
//call()方法 - 用於調用一個函數
fun.call(null,'function','張三');
  • Function的bind()方法

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

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

fun('李四');// this is 李四

var f = fun.bind(null, '張三');
f();// this is 張三
  • 重載是什麼

在其餘開發語言中 函數具備一種特性 叫作重載 重載就是定義多個同名的函數 但每個函數接受的參數的個數不一樣 程序會根據用時傳遞的實參個數進行判斷 具體調用的是哪一個函數
可是在JaveScript中 函數是沒有重載現象的 也就是說 若是同時定義多個同名的函數 只有最後一個定義的函數是有效的函數

/*
    重載的含義
    1.定義多個同名的函數,但具備數量不一樣的參數
    2.調用函數,根據傳遞參數的個數調用指定的函數
 */
function add(a,b){
    return a + b;
}
function add(a,b,c){
    return a + b + c;
}
function add(a,b,c,d){
    return a + b + c + d;
}

add(1,2);// 3
add(1,2,3);// 6
add(1,2,3,4);// 10

// JavaScript的函數不存在重載 -> 當函數同名時,最後一次定義的函數有效
console.log(add(1,2));// NaN
console.log(add(1,2,3));// NaN
console.log(add(1,2,3,4));// 10
  • arguments對象

JavaScript提供了arguments對象 該對象能夠模擬函數重載的現象 arguments對象是函數內部的本地變量 arguments已經再也不是函數的屬性了
arguments對象能夠獲取函數的全部參數 但arguments對象並非一個數組 而是一個類數組對象(沒有數組特有的方法)佈局

/*
    JavaScript提供arguments對象
    * 該對象存儲當前函數中全部的參數(實參) - 類數組對象
    * 場景 - 該對象通常用於函數中
    * 做用 - 用於獲取當前函數的全部參數
    * 屬性
    * length - 函數全部參數(實參)的個數
    * 用法 - 模擬實現函數的重載
 */
function add(){
    var num = arguments.length;
    switch (num) {
        case 2:
            return arguments[0] + arguments[1];
            break;
        case 3:
            return arguments[0] + arguments[1] + arguments[2];
            break;
        case 4:
            return arguments[0] + arguments[1] + arguments[2] + arguments[3];
            break;
    }
}
console.log(add(1,2));// 3
console.log(add(1,2,3));// 6
console.log(add(1,2,3,4));// 10
  • 函數的遞歸

調用自身的函數被稱之爲遞歸函數 在某種意義上說 遞歸近似於循環 二者都有重複執行相同的代碼 而且二者都須要一個終止條件以免無限循環或者無限遞歸性能

/* 函數的遞歸 -> 就是在指定函數的函數體中調用自身函數
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能夠將函數做爲數據使用 做爲函數本體 它像普通的數據同樣 不必定要有名字 默認名字的函數被稱之爲匿名函數this

function(a){return a;}
/*
    匿名函數的做用:
    1.將匿名函數做爲參數傳遞給其餘函數 - 回調函數
    2.將匿名函數用於執行一次性任務 - 自調函數
 */
  • 回調函數

當一個函數做爲參數傳遞給另外一個函數時 做爲參數的函數被稱之爲回調函數code

// 做爲另外一個函數(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.能夠將一個函數調用操做委託給另外一個函數(這意味着能夠節省一些代碼編寫工做)
3.回調函數也有助於提高性能對象

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

function fn(v){// 形參是一個函數
    return v(100);// 函數的調用體
}

// var result = fn(one);// 實參必須是一個函數

var result = fn(function(w){return w;});

console.log(result);
  • 自調函數

自調函數就是定義函數後自行調用

/*
    自調函數 - 定義即調用的函數
    * 第一個小括號 - 用於定義函數
    * 第二個小括號 - 用於調用函數
 */
// 全局做用域 - 生命週期: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.避免全局污染

相關文章
相關標籤/搜索