Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
JavaScript 函數有 4 種調用方式。
每種方式的不同方式在于 this 的初始化。
this 關鍵字
一般而言,在Javascript中,this指向函數執行時的當前對象。
注意 this 是保留關鍵字,你不能修改 this 的值。 |
調用 JavaScript 函數
我們知道如何創建函數。
函數中的代碼在函數被調用后執行。
作為一個函數調用
實例
function myFunction(a, b) {
return a * b;
}
myFunction(10, 2); // myFunction(10, 2) 返回 20
以上函數不屬于任何對象。但是在 JavaScript 中它始終是默認的全局對象。
在 HTML 中默認的全局對象是 HTML 頁面本身,所以函數是屬于 HTML 頁面。
在瀏覽器中的頁面對象是瀏覽器窗口(window 對象)。以上函數會自動變為 window 對象的函數。
myFunction() 和 window.myFunction() 是一樣的:
實例
function myFunction(a, b) {
return a * b;
}
window.myFunction(10, 2); // window.myFunction(10, 2) 返回 20
這是調用 JavaScript 函數常用的方法, 但不是良好的編程習慣 全局變量,方法或函數容易造成命名沖突的bug。 |
全局對象
當函數沒有被自身的對象調用時, this 的值就會變成全局對象。
在 web 瀏覽器中全局對象是瀏覽器窗口(window 對象)。
該實例返回 this 的值是 window 對象:
實例
function myFunction() {
return this;
}
myFunction(); // 返回 window 對象
函數作為全局對象調用,會使 this 的值成為全局對象。使用 window 對象作為一個變量容易造成程序崩潰。 |
函數作為方法調用
在 JavaScript 中你可以將函數定義為對象的方法。
以下實例創建了一個對象 (myObject), 對象有兩個屬性 (firstName 和 lastName), 及一個方法 (fullName):
實例
var myObject = {
firstName:"John",
lastName: "Doe",
fullName: function () {
return this.firstName + " " + this.lastName;
}
}
myObject.fullName(); // 返回 "John Doe"
fullName 方法是一個函數。函數屬于對象。 myObject 是函數的所有者。
this對象,擁有 JavaScript 代碼。實例中 this 的值為 myObject 對象。
測試以下!修改 fullName 方法并返回 this 值:
實例
var myObject = {
firstName:"John",
lastName: "Doe",
fullName: function () {
return this;
}
}
myObject.fullName(); // 返回 [object Object] (所有者對象)
函數作為對象方法調用,會使得 this 的值成為對象本身。 |
使用構造函數調用函數
如果函數調用前使用了 new 關鍵字, 則是調用了構造函數。
這看起來就像創建了新的函數,但實際上 JavaScript 函數是重新創建的對象:
實例
// 構造函數:
function myFunction(arg1, arg2) {
this.firstName = arg1;
this.lastName = arg2;
}
// Thiscreates a new object
var x = new myFunction("John","Doe");
x.firstName; // 返回 "John"
構造函數的調用會創建一個新的對象。新對象會繼承構造函數的屬性和方法。
構造函數中 this 關鍵字沒有任何的值。this 的值在函數調用時實例化對象(new object)時創建。 |
作為函數方法調用函數
在 JavaScript 中, 函數是對象。JavaScript 函數有它的屬性和方法。
call() 和 apply() 是預定義的函數方法。 兩個方法可用于調用函數,兩個方法的第一個參數必須是對象本身。
實例
function myFunction(a, b) {
return a * b;
}
myFunction.call(myObject, 10, 2); // 返回 20
實例
function myFunction(a, b) {
return a * b;
}
myArray = [10,2];
myFunction.apply(myObject, myArray); // 返回 20
兩個方法都使用了對象本身作為第一個參數。 兩者的區別在于第二個參數: apply傳入的是一個參數數組,也就是將多個參數組合成為一個數組傳入,而call則作為call的參數傳入(從第二個參數開始)。
在 JavaScript 嚴格模式(strict mode)下, 在調用函數時第一個參數會成為 this 的值, 即使該參數不是一個對象。
在 JavaScript 非嚴格模式(non-strict mode)下, 如果第一個參數的值是 null 或 undefined, 它將使用全局對象替代。
通過 call() 或 apply() 方法你可以設置 this 的值, 且作為已存在對象的新方法調用。 |
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
數的編寫與使用
在程序設計語言中函數是一段具有特殊功能的代碼,同時也是一組可以重復使用的代碼。通過函數這一對象的使用,進一步提高了程序開發的模塊化與高度多的代碼復用性。各種程序設計語言都對函數的定義及使用有著嚴格的語法規則。本文主要介紹如何在JavaScript中定義函數、使用函數,并對遞歸函數這一特殊類型函數進行說明。
JavaScript中所定義的函數主要由函數定義關鍵字、函數名稱、函數參數、執行代碼段與函數返回值5部分所組成。同時要求函數在使用過程中需要先定義函數,再調用函數。JavaScript函數定義基本語法描述如下:
JavaScript函數定義基本語法
JavaScript函數定義基本語法描述如上圖,說明如下:
函數定義語法說明
函數定義完成之后,就可以通過調用該函數完成特定的功能。函數調用方式較為簡單,只需要給出函數名稱與所傳遞參數,如果參數為空,只需要給出名稱后面的括號即可。關于參數部分需要注意形參與實參概念的區分。其中在函數定義中用于解釋說明語言的參數為形參。在函數調用過程中替代形參參與實際運算的參數為實參。示例說明如下:
形參與實參示例說明
匿名函數(Anonymous function),顧名思義是指沒有名字的函數,即在上面給出的基本語法中functionName部分可以省略的函數。在JavaScript中提供兩類基本匿名函數定義方式,一種是將匿名函數封裝為表達式,一種是將匿名函數賦值給變量形式。兩類匿名函數基本語法描述如下:
匿名函數的定義形式
匿名函數定義形式描述如上圖所示,上文中計算解決值函數我們可以使用兩種方法改寫為匿名函數,實現描述如下:
匿名函數使用實例
遞歸函數是一類特殊的函數類型,簡單理解即為在一個函數的內部調用了該函數自身。在使用遞歸函數是需要注意產生遞歸的條件與遞歸終止的條件。如同循環控制語句一樣,沒有遞歸終止的條件,程序將會一直占用資源,無法結束釋放資源。遞歸函數的說明可以從階乘的計算這一案例展開說明。階乘計算過程描述如下:
階乘計算原理
階乘計算過程描述如上圖所示,我們可知階乘問題的解決主要在于遞推關系的挖掘與終止條件的確定。本例中遞推關系為N!=N*(N-1)!,終止條件為1!=1;在明確這兩點之后我們可以編寫遞歸函數實現問題求解。遞歸函數描述如下圖:
階乘問題的遞歸求解編程實現
爬樓梯問題是使用遞歸算法進行問題求解的經典案例之一,爬樓梯問題主要只是假設有N階樓梯,需要從最底層爬到最高層,在上樓過程中每步只允許上1層或者2層,計算爬到N層總共方法有多少種?
爬樓梯方法問題
爬樓梯方法問題采用遞歸思想還是比較簡單的,我們可以從小人最后一步考慮。小人上到最高層N層時只能有兩種方法:
①從N-2層跨越2層到達N層;
②從N-1層跨越1層到達N層;
則計算到達N層的方法f(n)就等于到達N-1層方法f(n-1)與達N-2層方法f(n-2)之和。這就找到了我們進行遞推的關系式,終止條件即為f(1)=1和f(2)=2;
因此我們可以編程實現計算,實現代碼如下:
爬樓梯遞歸求解代碼
本頭條號長期關注編程資訊分享;編程課程、素材、代碼分享及編程培訓。如果您對以上方面有興趣或代碼錯誤、建議與意見,可以聯系作者,共同探討。更多程序設計相關教程及實例分享,期待大家關注與閱讀!JavaScript基礎教程系列教程鏈接如下:
JavaScript基礎教程(六)流程控制之循環語句
JavaScript基礎教程(五)流程控制之條件語句
avaScript是一種發展迅速的語言。這篇文章,我想展示一些有關如何在JavaScript中應用函數式編程的示例。
即使函數式編程可以極大地改善應用程序的代碼,但其原理在開始時可能會有些挑戰。由于詳細解釋所有這些都將花費大量時間,因此我們決定使用兩個實際的代碼示例來介紹這些概念
在第一個示例中,我們找到一種避免驗證變量是否為Null的方法。假設在我們的應用程序中,我們可以找到具有以下格式的用戶:
const someUser = {
name: 'some_name',
email: 'some@email.com',
settings: {
language: 'sp'
}
};
有一個功能,可以以用戶設置的語言返回歡迎消息。
const allGreetings = {
'en': '嗨',
'sp': '你好',
'fr': '歡迎你'
};
const getGreetingForUser = (user) => {
//將要執行
}
來看一個遵循命令式模型的“ getGreetingForUser”函??數的實現:
const getGreetingForUser = (user) => {
if (!user) {
return allGreetings.en;
}
if (user.settings && user.settings.language) {
if (allGreetings[user.settings.language]) {
return allGreetings[user.settings.language]
} else {
return allGreetings.en;
}
} else {
return allGreetings.en;
}
};
console.log(getGreetingForUser(someUser));
如上面所看到的,必須檢查用戶是否已經存在,是否已設置語言,以及是否已準備好歡迎消息。如果出現問題,我們將以默認語言返回一條消息。
現在,讓我們看一下相同的函數,但是這次我們將在其實現中使用函數式編程:
const getGreetingForUser = (user) => {
return RamdaFantasy.Maybe(user)
.map(Ramda.path(['settings', 'language']))
.chain(maybeGreeting);
};
const maybeGreeting = Ramda.curry((greetingsList, userLanguage) => {
return RamdaFantasy.Maybe(greetingsList[userLanguage]);
})(allGreetings);
console.log(getGreetingForUser(someUser).getOrElse(allGreetings.en));
為了處理可能為null或未定義的情況,我們將使用Maybe Monad。這使我們可以在對象周圍創建包裝器,并為空對象分配默認行為。
讓我們比較兩種解決方案:
//代替驗證用戶是否為空
if (!user) {
return allGreetings.en;
}
//我們將用:
RamdaFantasy.Maybe(user) //我們將用戶添加到包裝器中
//代替:
if (user.settings && user.settings.language) {
if (allGreetings[user.settings.language]) {
//我們將用:
<userMaybe>.map(Ramda.path(['settings', 'language'])) //如果存在數據,映射將會用它
//不是在else中返回默認值:
return indexURLs['en'];
.getOrElse(allGreetings。EN)
// 指定的默認值。
當我們知道存在空錯誤時的默認行為時,Maybe Monad非常有用。
但是,如果我們有一個引發錯誤的函數,或者我們將各種引發錯誤的函數鏈接在一起,并且我們想知道哪個發生了故障,則可以改用Either Monad。
現在,讓我們假設我們要計算產品的價格,同時考慮增值稅和可能的折扣。我們已經有了以下代碼:
const withTaxes = (tax, price) => {
2
if (!_.isNumber(price)) {
3
return new Error("Price is not numeric");
4
}
5
return price + (tax * price);
6
};
7
const withDiscount = (dis, price) => {
8
if (!_.isNumber(price)) {
9
return new Error("Price is not numeric");
10
}
11
if (price < 5)
12
return new Error("Discounts not available for low-priced items");
13
}
14
return price - (price * dis);5
};
const isError = (e) => e && e.name === 'Error';
const calculatePrice(price, tax, discount) => {
//將要執行
}
讓我們來看一個遵循命令式模型的“ calculatePrice”函數的實現:
const calculatePrice = (price, tax, discount) => {
const priceWithTaxes = withTaxes(tax, price);
if (isError(priceWithTaxes)) {
return console.log('Error: ' + priceWithTaxes.message);
}
const priceWithTaxesAndDiscount = withDiscount(discount, priceWithTaxes);
if (isError(priceWithTaxesAndDiscount)) {
return console.log('Error: ' + priceWithTaxesAndDiscount.message);
}
console.log('Total Price: ' + priceWithTaxesAndDiscount);
}
//我們計算出價值25的產品(含21%的增值稅和10%的折扣)的最終價格。
calculatePrice(25, 0.21, 0.10)
現在,讓我們了解如何使用Either Monad重寫此函數。
都有兩個構造函數,Left和Right。我們要實現的是將異常存儲到Left構造函數,并將正常結果(快樂路徑)存儲到Right構造函數。
首先,將更改已經存在的withTaxes和withDiscount函數,以便在出現錯誤時它們返回Left,在一切正常的情況下返回Right:
const withTaxes = Ramda.curry((tax, price) => {
if (!_.isNumber(price)) {
return RamdaFantasy.Either.Left(new Error("Price is not numeric"));
}
return RamdaFantasy.Either.Right(price + (tax * price));
});
const withDiscount = Ramda.curry((dis, price) => {
if (!_.isNumber(price)) {
return RamdaFantasy.Either.Left(new Error("Price is not numeric"));
}
if (price < 5) {
return RamdaFantasy.Either.Left(new Error("Discounts not available for low-priced items"));
}
return RamdaFantasy.Either.Right(price - (price * dis));
});
然后,我們為Right案例創建一個函數(顯示價格),為Left案例創建另一個函數(顯示錯誤),然后使用它們創建Either Monad:
const showPrice = (total) => { console.log('Price: ' + total) };
const showError = (error) => { console.log('Error: ' + error.message); };
const eitherErrorOrPrice = RamdaFantasy.Either.either(showError, showPrice);
最后,只需要執行Monad來計算最終價格:
//計算出價值25的產品(含21%的增值稅和10%的折扣)的最終價格。
eitherErrorOrPrice(
RamdaFantasy.Either.Right(25)
.chain(withTaxes(0.21))
.chain(withDiscount(0.1))
)
正如我們所看到的,一旦用Maybe和Either單子分解了代碼,就沒有那么復雜了。如果使用得當,它們可以使我們的代碼更易于閱讀和維護。
唯一的不便是我們需要克服的初始障礙,但這可以通過在網上一些示例并進行一些測試來完成。
喜歡可以關注一下哦。
半夜的一次斜眸,我發現了支付寶灰色產業的一角
得知開源會削弱對中國的技術封鎖,特朗普氣炸了
用漫畫讓你清楚了解linux內核,看懂了么?
你用大量 if else,而不用switch的原因,if真香啊
能在996公司久呆的人,到底有多會劃水?
*請認真填寫需求信息,我們會在24小時內與您取得聯系。