JavaScript 函數詳解
1 定義函數與函數調用
定義方式一
絕對值函數
function abs(x){
if(x >= 0){
return x;
}else{
return -x;
}
}
一旦執行到return,函數結束,返回結果!
如果沒有執行return,函數執行完後也會返回結果,結果是undefined
定義方式二
var abs = function(x){
if(x >= 0){
return x;
}else{
return -x;
}
}
function(x){…}這是一個匿名函數,但是可以把結果賦值給abs,通過abs就可以調用函數!
注:方法一與方法二等價!
調用函數
abs(10) //10
abs(-10) //10
2 參數獲取
參數問題:JavaScript可以傳任意個參數,也可以不傳參數。
手動拋出異常,規避無參數問題
function abs(x){
if (typeof x!=='number'){
throw 'Not a Number';
}
if (x>=0){
return x;
}else{
return -x;
}
}
測試結果:
arguments關鍵字
arguments一個js免費贈送的關鍵字;代表傳遞進來的所有的參數是一個數組。
測試代碼:
function abs(x){
console.log("x=>" +x);
for (var i = 0; i < arguments.length; i++){
console.log(arguments[i]);
}
if (x>=0){
return x;
}else{
return -x;
}
}
測試結果:
rest 參數
rest參數類似於Java中的"…",用於接收除了特定參數之外剩餘的所有參數,組成爲一個數組。
測試代碼:
function fun(a,b,...rest) {
console.log("a=>"+a);
console.log("b=>"+b);
console.log(rest);
}
測試結果:
注意:rest參數只能寫在最後面,使用"…rest"標識。
3 變量的作用域
在JavaScript中,var定義的變量是有作用域的。
在函數體中聲明,在函數體外不可以使用。
'use strict';
function f() {
var x = 1;
x = x + 1;
}
x=x+2; //Uncaught ReferenceError: x is not defined
同時,內部函數成員可以訪問外部函數的成員,反之則報錯。
假設內部函數變量和外部函數的變量重名,從自身函數開始由‘內’向‘外’查找,假設外部存在一個相同的變量,則內部屏蔽外部變量。
提升變量的作用域
function f() {
var x = 'x' +y;
console.log(x);
var y = 'y';
}
f();
結果:xundefined
說明:js執行引擎,自動提升y的聲明,但是不會提升變量y的賦值。
爲了更好代碼維護,將所有變量的定義放置在頭部。
全局變量
將變量定義在函數外部,則聲明週期是整個線程。
'use strict'
// 全局變量
var x = 1;
function f() {
console.log(x);
}
f();
console.log(x);
//測試結果:
1
1
JavaScript實際上只有一個全局作用域,任何變量(函數也可以視作變量),假設沒有在函數作用範圍內找到,就會向外查找,如果在全局作用域都沒有找到,報錯RefrenceError
規範
由於所有的全局變量均會綁定到window上,如果不同的js文件,使用了相同的全局變量,就會引發衝突,所以,如何能夠減少衝突?
'use strict'
//唯一全局變量;
var DemutApp = {};
//定義全局變量
DemutApp.name = 'Demut';
DemutApp.add = function (a,b) {
return a+b;
}
把自己的代碼全部放到自己定義的唯一空間名字中,解決全局命名,衝突的問題。
局部作用域let
請看👇問題:
測試代碼:
function f() {
for (var i = 0; i < 10; i++) {
console.log(i);
}
console.log(i+1); //正常情況下i不可以被使用,而此處確可以
}
f();
運行結果:
故爲解決局部作用域衝突問題,在ES6中引入了let關鍵字。
故將以上for循環中var
改爲let
後,迴歸正常。結果如下:
建議以後使用let
定義局部作用域的變量。
常量const
在ES6之前,使用全部大寫字母命名的變量,稱爲常量,建議不要修改這樣的值。
var PI = '3.14';
console.log(PI);
PI = '213'; //值是可以改變的,只是約定不改變
console.log(PI);
這種約定的方法確實不規範,所以ES6引入const
關鍵字,規範以上問題。
const PI = '3.14';
console.log(PI);
PI = '213'; //報錯
console.log(PI);
4 方法
定義方法
方法就是把函數放在對象的裏面,對象只有兩個東西:屬性和方法。
var Demut = {
name:'demut',
birth: 2000,
//方法:
age: function () {
//今年-出生年
var now = new Date().getFullYear();
return now - this.birth; //this指向本對象
}
}
//屬性
Demut.name
//方法,一定要帶()
Demut.age()
運行結果:
以上代碼有另一種表示:
function getAge() {
//今年-出生年
var now = new Date().getFullYear();
return now - this.birth;
}
var Demut = {
name:'demut',
birth: 2000,
//方法:
age: getAge()
}
//Demut.age() => 20
//getAge() => NaN
說明:getAge()中的this只能指向調用它的那個對象,如果沒有對象,則默認指向window,window中沒有birth屬性,故返回NaN。
在Java中this
是嚴謹的,只能指向本對象,但在Javascript中,可以使用apply
控制this
的指向。以下介紹apply:
apply
在js中apply可以控制this的指向。
測試代碼:
//代碼同上,在瀏覽器控制檯中輸入以下代碼
getAge.apply(Demut,[]) //this指向Demut, []表示傳入參數爲空
運行結果:
寫在最後
又如鷹攪動巢穴,在雛鷹以上兩翅搧展,接取雛鷹,背在兩翼之上。
——申命記32:11To Demut and Dottie!