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函數的4種調用方法。分享給大家供大家參考,具體如下:
JavaScript 函數有 4 種調用方式:
分述如下:
每種方式的不同方式在于 this 的初始化。
作為一個函數調用
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
當函數沒有被自身的對象調用時, this 的值就會變成全局對象。
在 web 瀏覽器中全局對象是瀏覽器窗口(window 對象)。
該實例返回 this 的值是 window 對象:
function myFunction() { return this; } myFunction(); // 返回 window 對象
函數作為全局對象調用,會使 this 的值成為全局對象。
使用 window 對象作為一個變量容易造成程序崩潰。
函數作為方法調用
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; } // This creates 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; } myObject = myFunction.call(myObject, 10, 2); // 返回 20 function myFunction(a, b) { return a * b; } myArray = [10, 2]; myObject = myFunction.apply(myObject, myArray); // 返回 20
兩個方法都使用了對象本身作為第一個參數。 兩者的區別在于第二個參數: apply傳入的是一個參數數組,也就是將多個參數組合成為一個數組傳入,而call則作為call的參數傳入(從第二個參數開始)。
在 JavaScript 嚴格模式(strict mode)下, 在調用函數時第一個參數會成為 this 的值, 即使該參數不是一個對象。
在 JavaScript 非嚴格模式(non-strict mode)下, 如果第一個參數的值是 null 或 undefined, 它將使用全局對象替代。
以下是總結出來最全前端框架視頻,包含: javascript/vue/react/angualrde/express/koa/webpack 等學習資料。
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小時內與您取得聯系。