文章目錄
重新鞏固JS系列,都是比較基礎的東西,可以進行查漏補缺,很快看完,這是第四篇。
其他JS重新鞏固系列:
1. 函數概述
在編程領域中,子程序是一個大型程序中的某部分代碼,由一個或多個語句塊組成。它負責完成某項特定任務,而且相較於其他代碼,具備相對的獨立性。一般會有輸入參數並有返回值,提供對過程的封裝和細節的隱藏。不同語言中,子程序的叫法:
在JS中,子程序成爲函數(function)。如果函數掛載在一個對象上,就稱它爲對象的方法。例子:
// 兩數求和函數
function sum(numA, numB) {
return numA + numB;
}
// 對象的方法
const person = {
//person對象的方法
getName: function() {
return this.name;
}
}
JS中,函數也是對象,程序可以隨意操控它們,比如賦值給變量、作爲參數傳遞給其他函數、可以給它們設置屬性和方法。
2. 函數定義
使用關鍵字 function定義,通常有2種方式: 函數聲明語句和函數表達式。
// 函數聲明語句: sum爲函數名,numA、num爲形參。
function sum(numA, numB) {
return numA + numB;
}
// 函數表達式
const sum = function(numA, numB) {
return numA + numB;
}
函數返回值使用return關鍵字, 沒有return語句則默認返回undefined。
第三種定義的方式是使用Function構造函數。最後一個參數是函數體,之前的都是函數的形參。
const sum = new Function('numA', 'numB', 'return numA + numB');
備註:一般不使用Function構造函數的形式(使用的場景:比如將一段字符串轉化爲可執行的代碼時)。
3. 函數調用
函數名稱加一對括號就可以調用函數。括號中可以傳入實參,和形參一一對應。
function sum(sumA, sumB) {
return numA + numB;
}
const result = sum(1, 2);
console.log(result); // 3
4. 函數參數
定義函數時,形參不需要指定類型,調用函數時也不會檢查實參的類型和個數。
function sum() {
return '?';
}
const result = sum(1, 2);
console.log(result); // 正常執行,輸出:?
4.1 默認值
函數參數可以指定默認值,如果調用時沒有傳入對應的值,則會使用默認值。
function sum(numA, numB = 2) {
return numA + numB;
}
console.log(sum(1)); // 3
4.2 剩餘參數
ES6新增:如果函數的最後一個命名參數以...
爲前綴,則它是包含剩餘參數的數組。
function sum(numA, ...nums) {
if (nums) {
for(let i = 0; i < nums.length; i++) {
numA += nums[i]
}
}
return numA;
}
console.log(sum(1)); // 1
console.log(sum(1, 2, 3)); // 6
5. 函數內部屬性
在函數內部,有2個特殊對象: arguments 和 this。
5.1 arguments對象
在函數體內,arguments表示實參列表對象,它是一個類數組對象(類數組中的“類”字表示像的意思,就是說arguments對象像數組),可以通過下標訪問對應的實參值,也有length屬性,但是沒有數組的一些方法。
function sum() {
return arguments[0] + arguments[1];
}
console.log(sum(1, 2)); // 3
5.2 this對象
在函數體內,this是指函數執行的環境對象(也叫context,即函數上下文)。一般來說,this指向調用函數的對象,如果沒有,就是全局對象,在瀏覽器中即爲Window對象(Node環境中爲Global對象)。
const sum = function () {
console.log(this);
}
// 嚴格模式下是 undefined, 非嚴格模式下是 Window(Node環境爲Global)
sum();
const obj = {
sum: function () {
console.log(this);
}
};
// this 爲 obj 對象
obj.sum();
6. 函數是特殊對象
函數是特殊的對象,意味着它也是一種值。所以函數可以: 當作參數傳遞、賦值給變量、作爲數組的元素中等。
function callSomeFunction (func, arg) {
return func(arg);
}
function sum(sum) {
return 1 + sum;
}
console.log(callSomeFunction(sum, 2)); // 3
函數具有的屬性:length 和 name。 方法: call、apply、bind。
6.1 函數的屬性:length 和 name
6.1.1 length屬性
函數的length是該函數期望參數的個數(第一個有默認參數前的參數),不包括有默認值參數和剩餘參數。
function sum(numA, numB = 1, ...nums) { }
console.log(sum.length); // 1
function sum(numA, numB = 1, numC, ...nums) { }
console.log(sum.length); // 1
6.1.2 name屬性
函數的name屬性是該函數的名稱。
const sum1 = function () {}
const obj = {
sum2: function () {}
}
const sum3 = new Function();
console.log(sum1.name); // sum1
console.log(obj.sum2.name); // sum2
console.log(sum3.name); // anonymous
6.2 函數的方法: call、apply、bind
6.2.1 call方法
調用函數,可以指定函數中this和傳入參數列表。
const obj = {
name: 'cc',
say: function (content) {
const speak = function () {
console.log(`${this.name} say ${content}`)
};
speak();
}
};
obj.say('welcome'); // say welcome
以上示例中,在say方法中調用speak,由於speak方法是直接單獨調用的,所以函數體內的this指向的是全局變量window,而全局變量window的name屬性值爲空(''
),所以輸出'' say welcome
。
提問:①函數speak中的this.name如何取到cc這個值? ②函數speak如何接收更多參數?
解決方法:
① speak() -----> speak.call(this) ,即可。
② speak() -----> speak.call(this, ‘one’, ‘two’) ,在call函數第一個參數後面依次添加參數即可。
6.2.2 apply方法
調用函數,可以指定函數中的 this 和傳入 參數數組 ,作用其實和call方法一樣,只是後面的參數是以數組的形式傳入。助記方法: apply----->首字母a,數組array的首字母也是a------->apply方法傳參是以數組的形式。
6.2.3 bind方法
生成一個新的函數,可以指定函數調用時的this對象和傳入參數列表。
6.2.1中同樣的兩個問題的解法:
① 因爲bind方法是生成一個新的方法,我們需要再調用這個新方法才能得到執行結果:
const obj = {
name: 'cc',
say: function (content) {
const speak = function () {
console.log(`${this.name} say ${content}`)
};
const speak1 = speak.bind(this);
speak1()
}
};
obj.say('welcome'); // cc say welcome
② 傳參的話,直接在bind函數中的第一個參數後面以參數列表的形式傳入即可。
const speak1 = speak.bind(this, 'one', 'two')
7. 變量作用域簡介
JS引擎查找變量的過程,從局部作用域向外層查找,一直到全局作用域爲止。
局部變量的名字可以和全局變量相同,但兩者互不影響。
const name = 'cc1';
function outerFunc() {
const name = 'cc2';
function innerFunc() {
const name = 'cc3';
console.log(name); // 'cc3'
}
innerFunc()
console.log(name); // 'cc2'
}
outerFunc();
console.log(name); // 'cc1'
ES6塊級作用域:ES6引入了let
、const
,它們聲明的是塊級作用域變量,塊由{...}
構成。
let x = 10;
var y = 10;
{
let x = 5;
var y = 5;
{
let x = 2;
var y = 2;
console.log(x, y) // 2 2
}
console.log(x, y) // 5 2
}
console.log(x, y) // 10 2
原型相關感興趣的可以看看這篇文章:幫你徹底搞懂JS中的prototype、__proto__與constructor(圖解)
8. 箭頭函數(arrow function)
箭頭函數表達式的語法比函數表達式更短,並且不綁定自己的this、arguments、super或new.target。這些函數表達式最適合用於非方法函數,並且它們不能用作構造函數。
const materials = ['Hydrogen', 'Helium', 'Lithium', 'Beryllium'];
materials.map(function (material) {
return material.length;
}); // [8, 6, 7, 9]
materials.map((material) => {
return material.length;
}); // [8, 6, 7, 9]
materials.map(material => material.length ); // [8, 6, 7, 9]
若對你有幫助,可以支持一下作者創作更多好文章哦~