首頁 > web前端 > js教程 > javascript中call與apply的應用

javascript中call與apply的應用

php中世界最好的语言
發布: 2018-03-14 13:30:03
原創
1418 人瀏覽過

這次帶給大家javascript中call與apply的應用,javascript中call與apply應用的注意事項有哪些,下面就是實戰案例,一起來看一下。

求陣列的最大值與最小值

定義一個陣列:

var ary = [23, 34, 24, 12, 35, 36, 14, 25];
登入後複製

排序再取值法

##先給陣列進行排序(小—>大),第一個和最後一個就是我們想要的最小值和最大值。

var ary = [23, 34, 24, 12, 35, 36, 14, 25];
ary.sort(function (a, b) {
    return a - b;
});var min = ary[0];var max = ary[ary.length - 1];
console.log(min, max);1234567
登入後複製

假設法

假設目前數組中的第一個值是最大值,然後拿這個值和後面的項逐一進行比較,如果後面某一個值比假設的還要打,說明假設錯了,我們把假設的值進行替換…..

var max = ary[0], min = ary[0];for (var i = 1; i < ary.length; i++) {
    var cur = ary[i];
    cur > max ? max = cur : null;
    cur < min ? min = cur : null;
}
console.log(min, max);1234567
登入後複製

Math中的max/min方法實現(透過apply)

直接使用Math.min

var min = Math.min(ary); 
console.log(min); // NaN 
console.log(Math.min(23, 34, 24, 12, 35, 36, 14, 25));
登入後複製

直接使用Math.min的時候,需要把待比較的那堆數一個個的傳遞進去,這樣才可以得到最後的記過,一下放一個ary數組進去是不可以的。


嘗試:使用eval

var max = eval(“Math.max(” + ary.toString() + “)”); 
console.log(max); 
var min = eval(“Math.min(” + ary.toString() + “)”); 
console.log(min); 
“Math.max(” + ary.toString() + “)” –> “Math.max(23,34,24,12,35,36,14,25)”
登入後複製

首先不要管其他的,先把我們最後要執行的程式碼都變成

字串,然後把陣列中的每一項的值分別的拼接到這個字串中。

eval:把一個字串變成JavaScript表達式執行 

例如:eval(“12+23+34+45”) // 114

#透過apply調用Math中的max/min

var max = Math.max.apply(null, ary); 
var min = Math.min.apply(null, ary); 
console.log(min, max);
登入後複製

在非嚴格模式下,給apply的第一個參數為null的時候,會讓max/min中的this指向window,然後將ary的參數一個個傳給max/min。


求平均數

現在模擬一個場景,進行某項比賽,評審打分後,要求去掉一個最高分和最低分,剩下分數求得的平均數即為最後分數。

可能很多同學會想到用,寫一個方法,讓後接收所有的分數,然後用函數的內建屬性arguments,把arguments呼叫sort方法排序,然後…,但是要注意,arguments並不是真正的數組對象,它只是偽數組集合而已,所以直接調用用arguments調用sort方法是會報錯的:

arguments.sort(); // Uncaught TypeError: arguments.sort is not a function
登入後複製

那麼這時候可不可以先將arguments轉換為一個真正的數組呢,然後再進行操作呢,按照這個思想,我們自己實現一個實現題目要求的業務方法:

function avgFn() {
    // 1、将类数组转换为数组:把arguments克隆一份一模一样的数组出来
    var ary = [];    for (var i = 0; i < arguments.length; i++) {
        ary[ary.length] = arguments[i];
    }    // 2、给数组排序,去掉开头和结尾,剩下的求平均数
    ary.sort(function (a, b) {
        return a - b;
    });
    ary.shift();
    ary.pop();    return (eval(ary.join(&#39;+&#39;)) / ary.length).toFixed(2);
}var res = avgFn(9.8, 9.7, 10, 9.9, 9.0, 9.8, 3.0);
console.log(res);1234567891011121314151617
登入後複製

我們發現在自己實現的avgFn方法中有一個步驟為將arguments克隆出來生成是一個數組。如果對數組的slice方法比較熟悉的話,可以知道當slice方法什麼參數都不傳的時候就是克隆當前的數組,可以模擬為:

function mySlice () {
    // this->当前要操作的这个数组ary
    var ary = [];    for (var i = 0; i < this.length; i++) {
        ary[ary.length] = this[i];
    }    return ary;
};var ary = [12, 23, 34];var newAry = mySlice(ary);
console.log(newAry);1234567891011
登入後複製

所以在avgFn方法中的將arguments轉換為數組的操作可以透過call方法來借用Array中的slice方法。

function avgFn() { // 1、将类数组转换为数组:把arguments克隆一份一模一样的数组出来 // var ary = Array.prototype.slice.call(arguments); var ary = [].slice.call(arguments);
// 2、给数组排序,去掉开头和结尾,剩下的求平均数....123
}
登入後複製

我們現在的做法是先將arguments轉換為數組,然後再操作轉換之後的數組,那麼可以不可以直接就用arguments而不要先轉換為數組呢? 當然是可以的,透過call來借用數組的方法來實現。


function avgFn() {
    Array.prototype.sort.call(arguments , function (a, b) {
        return a - b;
    });
    [].shift.call(arguments);
    [].pop.call(arguments);    return (eval([].join.call(arguments, &#39;+&#39;)) / arguments.length).toFixed(2);
}var res = avgFn(9.8, 9.7, 10, 9.9, 9.0, 9.8, 3.0);
console.log(res);123456789101112
登入後複製

將類別數組轉換數組

在之前提到了借用數組的slice方法將類別數組物件轉換為數組,那麼透過

getElementsByTagName等方法獲取的類別數組物件是不是也可以藉用slice方法來轉換成陣列物件呢?

var oLis = document.getElementsByTagName('div'); 

var ary = Array.prototype.slice.call(oLis); 
console.log(ary); 
#在標準瀏覽器下,的確可以這麼用,但在IE6~8下就悲劇了,會報錯:

SCRIPT5014: Array.prototype.slice: 'this' 不是JavaScript 物件(報錯) 

#那麼在IE6~8下就只能透過循環一個個加到數組中了:

for (var i = 0; i < oLis.length; i++) { 
ary[ary.length] = oLis[i]; 
}
登入後複製

注意:對於arguments借用數組的方法是不存在任何相容性問題的。


基於IE6~8和標準瀏覽器中的區別,抽取類別數組物件轉換為數組的工具類別:

function listToArray(likeAry) {
    var ary = [];    try {
        ary = Array.prototype.slice.call(likeAry);
    } catch (e) {        for (var i = 0; i < likeAry.length; i++) {
            ary[ary.length] = likeAry[i];
        }
    }    return ary;
}1234567891011
登入後複製

這個工具方法中用到了瀏覽器的異常資訊捕獲,那麼這裡也介紹一下吧。

console.log(num); 

當我們輸出一個沒有定義的變數的時候會報錯:Uncaught ReferenceError: num is not defined,在JavaScript中,本行報錯,下面的程式碼都不再執行了。

但是如果使用了try..catch捕獲異常訊息的話,則不會影響下面的程式碼進行執行,如果try中的程式碼執行出錯了,會預設的去執行catch中的try { 


console.log(num); 
} catch (e) { // 形参必须要写,我们一般起名为e 
console.log(e.message); // –> num is not defined 可以收集当前代码报错的原因 
} 
console.log(‘ok’);
登入後複製

所以try…catch的使用格式為(和Java中很像):


try { 
// 
} catch (e) { 
// 如果代码报错执行catch中的代码 
} finally { 
// 一般不用:不管try中的代码是否报错,都要执行finally中的代码 
}
登入後複製

這個時候既想捕獲到信息,又不想讓下面的diamante執行,那麼該怎麼做呢?

try {    console.log(num);
} catch (e) {    // console.log(e.message); // --> 可以得到错误信息,把其进行统计    // 手动抛出一条错误信息,终止代码执行    throw new Error(&#39;当前网络繁忙,请稍后再试&#39;);    // new ReferenceError --> 引用错误    // new TypeError --> 类型错误    // new RangeError --> 范围错误
}console.log(&#39;ok&#39;);
登入後複製
我相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!

推薦閱讀:

javascript中call與apply以及bind有哪些不同
#

javascript中call詳解

#

以上是javascript中call與apply的應用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板