亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

JavaScript函數詳解

2019-11-20 13:05:37
字體:
來源:轉載
供稿:網友

1、函數定義

 函數包含一組語句,它們是javascript的基礎模塊單元,用于代碼復用、信息隱藏和組合調用。函數用于指定對象的行為

2、函數的四種調用模式及this的初始化

第一種:方法調用模式
    以下事例證明通過方法調用模式調用時,this綁定到擁有該方法的對象。如:

復制代碼 代碼如下:

var person = {
    name: "defaultName",
    setName : function(name){
        this.name = name;
    }
};
person.setName("zhangsan");
alert(person.name);

第二種:函數調用模式
    以下事例證明通過函數調用模式調用時,this綁定到全局對象上。如:

復制代碼 代碼如下:

var test = add(value1, value2);
var name = "defaultName";
var person = {
    name: "zhangsan", // person中定義的name
    getName : function(){
        // 通過此方法可以將test函數的this改變為person的this對象
        var that = this;  // 解決方案
        // getName中定義的name
        var name = "lisi";
        var test = function(){
            // 通過that來訪問person中的對象
            // this指向Global對象
            // this.name = defaultName
            // that.name = zhangsan
            alert([this.name, that.name]);
        };
        test(); // 函數調用模式
    }
}
person.getName();

第三種:構造器調用模式

復制代碼 代碼如下:

// 定義一個Person的構造器,在調用時一定要用new調用
var Person = function(name){
    this.name = name;
}
// 添加一個方法到Person
Person.prototype.getName = function(){
    return this.name;
};
// 構造一個Person對象
var person = new Person("zhangsan");
alert(person.getName()); // 調用getName獲取person對象中name屬性的值

第四種:Apply調用模式

復制代碼 代碼如下:

<script type="text/javascript">
    // 定一個累加方法。如sum(1,2,3,4...)
    // 該方法位于window執行環境中。
    var displayName = function(){
        alert("sum的執行環境: " + typeof(this));
        alert("Name: " + this.name); // 取出當前執行環境中name屬性
    }
    // 定一個Person對象
    var Person = {
        name: "zhangsan"
    };
    displayName.apply(Person);
</script>

3、Apply和call的區別

復制代碼 代碼如下:

// 定一個對象,包含一個add方法,返回a、b的和
var Person = {
    'add' : function(a, b){
        return a + b;
    }
};
// 顯示a、b的和
function showInfo(a, b){
    alert(this.add(a, b));
}
// 通過apply方法改變showInfo方法的this指向
//showInfo(1, 3); // 對象不支持次對象
showInfo.apply(Person, [1, 3]);
showInfo.call(Person, 1, 3);
// 從上面可以看出,apply和call的區別是apply接受一個數組作為被調函數的參數,
// 而call是通過將被調函數的所有參數以逗號分隔的形式展開

4、函數參數(arguments)
    arguments并不是一個數組,只是與數組相似。arguments除了擁有length屬性,數組的所有屬性和方法都不具備。用arguments來實現一個累加的函數。

復制代碼 代碼如下:

function sum(){
    var total = 0;
    for(var i=0; i<arguments.length; i++){ // arguments.length返回sum函數調用時傳遞參數的個數
        total += arguments[i];
    }
    return total;
}
alert("sum: " + sum(1, 3, 2, 4));

5、函數返回值(return)
    當一個函數被調用,通常會從函數的{開始執行到}結束。如果想提前結束該函數的執行可以使用return語句,此時,return語句后面的所有語句將永遠不會執行。如:

復制代碼 代碼如下:

function test(){
    alert("first");
    return;
    alert("second"); // 該語句永遠被不會執行
}
test();
// 一個函數總是會返回值,如果沒有使用return返回值,默認返回undefined。如:
function test(){
    alert("first");
}
alert(test()); // 輸出:undefined
// 如果函數前使用new方式調用,且返回值不是一個對象,則返回this(新對象)。如:
function test(){
    alert("first");
}
var t = new test();
alert(typeof t); // 輸出:‘object'
alert(t instanceof test); // 輸出:true

6、異常(exception)

    異常是干擾程序正常流程的非正常事故(可能人為有意的)。當檢查出這樣的事故,應當拋出異常。如:

復制代碼 代碼如下:

function add(a, b){ // 定義一個加法函數
    // 如果傳遞的參數不是數字類型,則拋出一個異常信息
    if(typeof a != 'number' || typeof b != 'number'){
        throw {
            'name'  : "typeError", // 屬性是自定義的,名字可以任意取
            'message': "add方法必須使用數字作為參數"
        };
    }
    return a + b;
}
(function(){
    // 捕獲add方法可能產生的異常
    try{
        add(10, "");
    } catch(e){
        // 一個try語句只有一個catch語句,如果要處理多個異常,則通過異常的name屬性來區別
        // 判斷異常的類型
        if(e.name === "typeError"){
            alert(e.message);
        }
    }
})();

7、給類型添加方法
    javascript中允許給基本類型添加方法。如:boolean、string、Number
    實例:在Function中添加一個method函數,該函數為Function添加其他自定義的函數(避免使用prototype),然后利用method函數想Function中添加一個add函數,最后測試add函數在Function中確實存在。該方法將func函數添加到Function中,以name命名。然后,返回Function的對象

復制代碼 代碼如下:

Function.prototype.method = function(name, func){
    // 避免覆蓋已有的方法
    if(!this.prototype[name]){
        this.prototype[name] = func;
    }
    return this;
};
// 通過Function.method方法添加一個加法函數到Function,該函數的名稱為“add”
Function.method("add", function(a, b){
    if(typeof a != 'number' || typeof b != 'number'){
        throw {
            'name'  : "typeError",
            'message' : "add方法必須傳入數字"
        };
    }
    return a + b;
});
// 調用Function的add方法是否存在
(function(){
    try{
        alert(Function.add(1, 3)); // 輸出:4
    } catch(e){
        if(e.name === 'typeError'){
            alert(e.message);
        }
    }
})();
// 去除字符串兩端的空白
String.method("trim", function(){
    return this.replace(/^/s+|/s+$/g, '');
});
alert('|' + "   hello world     ".trim() + '|'); // 輸出: '|hello world|'
// 添加數字的取整函數
Number.method("integer", function(){
    // 可以通過此種方式調用函數,如:Math.random() == Math['random']() == Math["random"]()
    return Math[this < 0 ? 'ceil' : 'floor'](this);
});
alert((-10 / 3).integer()); // 輸出:-3

8、遞歸調用(arguments.callee)
    遞歸調用就是自己調用自己。調用分為:直接調用和間接調用下面展示使用遞歸調用來計算指定值的斐波那契數列。

復制代碼 代碼如下:

// 求i的階乘
function factorial(i){
    if(i < 2){
        return 1;
    }
    return i*factorial(i-1); // 遞歸調用
}
alert(factorial(5)); // 求5的階乘
// 以上方式存在一個問題?如下:
var factorial = function(i){
    if(i < 2){
        return 1;
    }
    return i*factorial(i-1); // factorial還能被調用嗎?不能
}
var test = factorial;
factorial = null; 
alert(test(2));
// 解決方案:
var factorial = function(i){
    if(i < 2){
        return 1;
    }
    return i*arguments.callee(i-1); // arguments.callee返回正被執行的 Function 對象,也就是所指定的 Function 對象的正文
}
var test = factorial;
factorial = null;
alert(test(5));

9、作用域

復制代碼 代碼如下:

// 在程序中,作用域控制著變量的可見性和生命周期。
var name = "default"; // 全局作用域
function getName(){
    var name = "getName"; // getName作用域下
    for(var i=0; i<2; i++){
        var inName = "inName";
    }
    alert(i + "," + inName); // 2,inName 注意:在js中沒有塊級作用域,及if、for、while中聲明的變量是放在塊所在的作用域下
    return name;
}
alert(getName()); // getName 注意:js存在函數作用域,所以在函數內部定義的變量在外部是不可見的
alert(name); // default

注意:在現代的很多語言中,推薦將變量盡可能的延遲聲明。如:java而在js中,卻不推薦這樣做,因為js不支持塊級作用域。推薦在函數的開始就將所有用到的變量進行聲明。

10、閉包
    函數能夠訪問它被創建時環境的上下文稱為閉包。作用域的好處是,內部函數可以訪問外部函數的所有變量(除this和arguments)。

復制代碼 代碼如下:

var myObject = {
    value   : 0,
    increment : function(inc){
        this.value = typeof inc === 'number' ? inc : 1;
    },
    getValue  : function(){
        return this.value;
    }
};
myObject.increment(10);
alert(myObject.value);
alert(myObject.getValue());
// 上面使用字面常量方式定義了一個myObject對象。但是value變量可以被外部對象訪問
var myObject = function(){
    var value = 0;
    return {
        increment: function(inc){
            value += typeof inc === 'number' ? inc : 1;
        },
        getValue : function(){
            return value;
        }
    };
}();
myObject.increment(10);
alert(myObject.value); // 不能被外部對象訪問
alert(myObject.getValue()); // 10
// 漸變body的背景色(黃色到白色)
var fade = function(node){
    var level = 1;
    var step = function(){
        var hex = level.toString(16);
        node.style.backgroundColor = '#FFFF' + hex + hex;
        if(level < 15){
            level += 1;
            setTimeout(step, 500); // 如果level小于15,則內部函數自我調用
        }
    };
    setTimeout(step, 1); // 調用內部函數
};
fade(document.body);
// 下面是一個很糟糕的例子
<a href="#" name="test">點擊我...</a><br> // 點擊時顯示3
<a href="#" name="test">點擊我...</a><br> // 點擊時顯示3
<a href="#" name="test">點擊我...</a><br> // 點擊時顯示3
var add_the_handlers = function(nodes){
    var i;
    for(i = 0; i < nodes.length; i += 1) {
        nodes[i].onclick = function(e){ // 函數構造時的:i
            alert(i);
        };
    }
};
var objs = document.getElementsByName("test");
add_the_handlers(objs);
// 造成上面的原因是:a標簽的事件函數綁定了變量i,則不是函數在構造時的i值。
// 解決方案如下:
var add_the_handlers = function(nodes){
    var i;
    for(i = 0; i < nodes.length; i += 1) {
        nodes[i].onclick = function(i){
            return function(e){
                alert(i); // 輸出的i是構造函數傳遞進來的i,不是事件處理綁定的i。
            };
        }(i);
    }
};
var objs = document.getElementsByName("test");
add_the_handlers(objs);

11、回調(callbacks)

復制代碼 代碼如下:

// data表示參數,而call_function則表示回調函數
function sendRequest(data, call_function){
    // setTimeout來模仿客戶端請求服務端中傳輸數據的時間。
    // 當3秒鐘后就調用回調函數(有客戶端實現回調函數)
    setTimeout(function(){
        call_function(data); // 調用回調函數
    }, 3000);
}
// 測試sendRequest函數
sendRequest("參數", function(context){
    alert("context=" + context);
});

12、模塊
    模塊是一個提供接口而隱藏狀態和實現的函數或對象。
    一般形式:一個定義了私有變量和函數的函數;利用閉包創建可以訪問私有變量和函數的特權函數;最后返回這個特權函數,或者把他們保存到一個可以被訪問到的地方。

復制代碼 代碼如下:

Function.prototype.method = function(name,func){
    this.prototype[name] = func;
    return this;
};
String.method("deentityify",function(){
    var entity = {
        quot : '"',
        lt   : '<',
        gt   : '>'
    };
    return function(){
        return this.replace(/&([^&;]+);/g, function(a, b){ // 怎樣知道a、b的值,了解正則表達式
            var r = entity[b];
            return typeof r === "string" ? r : a;
        });
    };
}());
alert("<">".deentityify()); // 測試:<">

注:模塊模式通常結合單例模式使用,JavaScript的單例模式就是用對象字面量方式創建的對象,對象的屬性值可以是數值或函數,并且屬性值在該對象的生命周期中不會發生變化。

13、級聯(鏈式操作)
    對于一些不返回值的方法,我們返回this,而不是undefined,那么我們就可以啟動以級聯(鏈式)去操作該對象。如下:

復制代碼 代碼如下:

var $ = function(id){
    var obj = document.getElementById(id);
    obj.setColor = function(color){
        this.style.color = color;
        return this;
    };
    obj.setBgColor = function(color){
        this.style.backgroundColor = color;
        return this; // 返回this對象,啟動級聯
    };
    obj.setFontSize = function(size){
        this.style.fontSize = size;
        return this;
    };
    return obj;
};
$("test").setColor("red")
         .setFontSize("30px")
         .setBgColor("blue");
// 改進后的代碼:
(function(id){
    var _$ = function(id){
        this.element = document.getElementById(id);
    };
    _$.prototype = {
        setColor : function(color){
            this.element.style.color = color;
            return this;
        },
        setBgColor : function(color){
            this.element.style.backgroundColor = color;
            return this;
        },
        setFontSize : function(size){
            this.element.style.fontSize = size;
            return this;
        }
    };
    
    // 添加到window原型鏈中
    window.$ = function(id){
        return new _$(id);
    };
})();
$("test").setColor("red")
         .setFontSize("30px")
         .setBgColor("blue");

14、套用
    所謂套用就是將函數與傳遞給它的參數相結合,產生一個新的函數。如:下面代碼中定義一個add()函數,該函數能夠返回一個新的函數,并把參數值傳遞給這個新函數,從而實現連加操作。

復制代碼 代碼如下:

// 第一種方式:
var add = function(a){
    return function(b){
        return a + b;
    }
};
alert(add(1)(2)); // 3
// 第二種方式:用arguments實現
var add = function(){
    var arg = arguments;
    return function(){
        var sum = 0;
        for(var i=0; i<arg.length; i++){
            sum += arg[i];
        }
        for(i=0; i<arguments.length; i++){
            sum += arguments[i];
        }
        return sum;
    }
};
alert(add(1,2,3)(4,5,6)); // 21
// 第三種方式:通過一個套用方法(curry)實現
var add = function(){
    var sum = 0;
    for(var i=0; i<arguments.length; i++){
        sum += arguments[i];
    }
    return sum;
};
// 添加方法到Function的原型鏈上
Function.prototype.method = function(name, func){
    this.prototype[name] = func;
    return this;
};
// 套用方法
Function.method('curry', function(){
    // 通過數組Array的slice方法,使得arguments也具有concat方法
    var slice = Array.prototype.slice,
        args = slice.apply(arguments), that = this;
    return function(){
        return that.apply(null, args.concat(slice.apply(arguments)));
    };
});
alert(add.curry(1,2)(3,4)); // 10

15、記憶
    函數可以用對象去記住先前操作的結果,從而能避免無謂的運算。這種優化被稱為記憶。

復制代碼 代碼如下:

var fibonacci = function(){
    var mome = [0,1]; // 存放計算后的數據
    var fib = function(n){
        var result = mome[n];
        // 如果不存在被計算過的數據,則直接計算。然后在將計算結果緩存
        if(typeof result !== 'number'){
            result = fib(n-1) + fib(n-2);
            mome[n] = result;
        }
        return result;
    };
    return fib;
}();
for(var i=0; i<=10; i++){
    document.writeln("http:// " + i + ": " + fibonacci(i) + "<br/>");
}
//==========================
// 創建一個具有記憶的函數
//==========================
var memoizer = function(memo, fundamental){
    var shell = function(n){
        var result = memo[n];
        if(typeof result !== "number"){
            result = fundamental(shell, n);
            memo[n] = result;
        }
        return result;
    };
    return shell;
};
// 通過記憶函數memoizer完成斐波那契數列
var fibonacci = memoizer([0,1], function(shell, n){
    return shell(n-1) + shell(n-2);
});
// 通過記憶函數memoizer完成階乘
var factorial = memoizer([1,1], function(shell, n){
    return n * shell(n-1);
});
for(var i=0; i<=15; i++){
    document.writeln("http:// " + i + ": " + factorial(i) + "<br/>");
}

小伙伴們看明白了沒,非常實用吧,如有遺漏的地方,還請大神們指點下,共同進步

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品无码久久久久久国产| 亚洲免费视频一区二区| 亚洲成人av在线| 欧美性资源免费| 欧美精品18videos性欧美| 亚洲精品久久久久久下一站| 欧美综合在线观看| 久久久久久av| 超薄丝袜一区二区| 亚洲日本欧美中文幕| 亚洲欧洲av一区二区| 中文字幕一区电影| 久久精品精品电影网| 91在线观看免费高清完整版在线观看| 亚洲日本成人网| 2024亚洲男人天堂| 国产精品第一页在线| 欧美日韩另类在线| 成人欧美在线视频| 久久精品视频亚洲| 午夜精品www| 欧美国产日韩xxxxx| 亚洲人成绝费网站色www| 亚洲国产一区二区三区在线观看| 久久精品视频在线| 日韩精品一区二区视频| 亚洲精品aⅴ中文字幕乱码| 91精品国产成人www| 青青草国产精品一区二区| 欧美香蕉大胸在线视频观看| 欧美高清自拍一区| 精品国产一区二区三区久久久狼| 亚洲性日韩精品一区二区| 日韩av综合网站| 中文字幕久热精品在线视频| 亚洲最新在线视频| 成人网欧美在线视频| 久久亚洲精品国产亚洲老地址| 国产精品欧美一区二区三区奶水| 亚洲国产精品电影在线观看| 亚洲欧美国产日韩中文字幕| 青草成人免费视频| 国产欧美 在线欧美| 午夜欧美大片免费观看| 国产精品27p| 久久精品91久久香蕉加勒比| 91在线观看免费观看| 黄色91在线观看| xvideos国产精品| 91亚洲va在线va天堂va国| 国产成人免费av电影| 96精品视频在线| 亚洲免费成人av电影| 精品久久香蕉国产线看观看gif| 久久久久久久亚洲精品| 国产亚洲成av人片在线观看桃| 亚洲精品福利在线| 成人激情视频在线播放| 久久久精品一区二区三区| 中文字幕欧美日韩精品| 欧美猛男性生活免费| 日韩精品一区二区视频| 福利视频第一区| 精品福利一区二区| 国产精品日韩在线播放| 欧美人在线视频| 久久精品久久久久久国产 免费| 成人写真福利网| 欧美在线观看一区二区三区| 久久久久久久久91| 中文字幕欧美日韩va免费视频| 日韩av成人在线观看| 久久99视频精品| 日韩电视剧在线观看免费网站| 亚洲欧洲国产一区| 不卡av电影在线观看| 日韩久久免费电影| 亚洲a中文字幕| 在线观看欧美成人| 欧美一级高清免费| 久久人人97超碰精品888| 亚洲区中文字幕| 国产日韩精品视频| 欧美日韩国产一区中文午夜| 久久久成人精品| 久久人人爽人人爽爽久久| 不卡中文字幕av| 久久人91精品久久久久久不卡| 国内精品国产三级国产在线专| 日韩精品免费在线视频观看| 亚洲国产日韩欧美在线99| 88国产精品欧美一区二区三区| 国产美女扒开尿口久久久| 精品久久久久久久中文字幕| 国产精品99久久久久久白浆小说| 亚洲乱码一区av黑人高潮| 国产精品爽爽爽爽爽爽在线观看| 日韩av在线网页| 国产精品成人国产乱一区| 日韩hd视频在线观看| 九九热r在线视频精品| 亚洲四色影视在线观看| 亚洲午夜性刺激影院| 国产小视频国产精品| 亚洲黄色av网站| 国产午夜精品美女视频明星a级| 色偷偷88888欧美精品久久久| 欧美日韩在线一区| 亚洲精品中文字幕av| 亚洲伊人一本大道中文字幕| 91中文在线视频| 亚洲欧美国产精品| 亚洲va欧美va国产综合久久| 97国产精品免费视频| 国产不卡av在线免费观看| 日韩有码视频在线| 国产成人精品日本亚洲| 国产精品久久久久久av下载红粉| 尤物yw午夜国产精品视频明星| 欧美中文在线观看| 欧美极品在线视频| 欧美不卡视频一区发布| 欧美成aaa人片免费看| 国产日韩专区在线| 川上优av一区二区线观看| 国产国产精品人在线视| 日韩亚洲欧美中文在线| 欧美激情精品在线| 国产精品久久久久久亚洲调教| 国产成人涩涩涩视频在线观看| 成人av资源在线播放| 久久精品影视伊人网| 久久久国产影院| 欧美夫妻性生活xx| 亚洲精品www久久久久久广东| 在线电影av不卡网址| 91sao在线观看国产| 欧美日本精品在线| 国产99久久精品一区二区| 日韩最新在线视频| 欧美亚洲国产日本| 亚洲第一天堂无码专区| 久久成人亚洲精品| www.久久草.com| 久久久伊人欧美| 最近免费中文字幕视频2019| 日韩av在线天堂网| 成人黄色片网站| 国产精品综合网站| 日韩av在线看| 精品中文字幕在线观看| 国产精品 欧美在线| 欧美性猛交xxxx黑人| 亚洲欧美日韩直播| 精品久久久免费| 欧美日韩一二三四五区| 欧美大片大片在线播放| 在线日韩av观看| 国产一区二区黑人欧美xxxx| 国产精品久久久久影院日本| 成人性生交大片免费观看嘿嘿视频| 热99精品里视频精品| 亚洲精品国产品国语在线| 欧美日韩日本国产|