簡單介紹一下變數在JS中的幾個性質,之後的篇章會比較深入的講解,這些性質背後的原因們
var a=1;
var b='2'
var c=function(){return 3}
var d=false
console.log(typeof a); //number
console.log(typeof b); //string
console.log(typeof c); //function
console.log(typeof d); //boolean
JS不像Java一樣用int, String, boolean等關鍵字宣告變數。
JS的變數在ES6以前只有var,ES6以後也頂多新增了let, const,變數的typeof都需要等到賦值才能決定。
var a;
console.log(a); //undefined
console.log(typeof a); //undefined
用var宣告變數,初始化為undefined。還沒賦值前,無法判斷該變數的type
小結論:變數的type,用變數的value判斷
有效範圍講的專業一點叫作用域(scope)
,var變數是遵照 function scope
。
就是變數存在的地方。
有點像寄生物與宿主的關係,寄生物離開宿主多久就會死掉。
變數離開他的作用域,就會被垃圾回收機制給丟掉。燈燈燈燈燈燈燈燈燈,垃圾車來囉~
function scope
」講人話就是:var
關鍵字令出的變數,他的有效範圍以function
界定。
console.log('用var關鍵字 定義變數i')
console.log('--------------------------')
var i='全域變數';
console.log(`i=${i}`);
//`i=${i}` 等價於 'i='+i 字串連接
// ` 反引號在~鍵上面 (我一開始還找不到,所以特別寫這行)
console.log('--------------------------')
function fun(){
var i='function內變數';
console.log(`I'm in the function, i=${i}`)
};
fun();
console.log('--------------------------')
console.log(`I'm out of the function, i=${i}`);
console.log('--------------------------')
console.log("I'm in the for loop")
for(var i=0;i<5;i++){
console.log(`i=${i}`)
} //i=5離開for迴圈
console.log('--------------------------')
console.log(`I'm out of the for loop, i=${i}`);
用var關鍵字 定義變數i
--------------------------
i=全域變數
--------------------------
I'm in the function, i=function內變數
--------------------------
I'm out of the function, i=全域變數
--------------------------
I'm in the for loop
i=0
i=1
i=2
i=3
i=4
--------------------------
I'm out of the for loop, i=5
離開for loop
後,我們再次呼叫變數i
,得到的答案是:5。
原因是for loop
不是function
,會影響到在全域
用var
定義的變數i
。
var i='全域變數';
function outterFun(){
function innerFun(){
console.log(i)
}
return innerFun;
};
aNewFun=outterFun();
aNewFun(); //全域變數
outterFun
裡面的inner function
,找不到變數i
→ 往外向outterFun
找outterFun
找不到變數i
→向全域
找Uncaught ReferenceError: i is not defined
小結論:
function scope
首先先來釐清變數和屬性,他們有以下幾個關係:
一般情況,變數放在一個object裡面,那該變數就會叫object的屬性
function雖然是一個object,但var變數的作用域(scope)是以function為界,
所以function外,別想拿到function的內變數
function外,如果硬要存取內變數,可以把它從function return出來,變得與function本身同級。
function外,可以存取屬性。
沒錯,你沒看錯,function可以有屬性,因為function是object嘛~~
function aFun(){
let a='function內變數';
return a; //可以透過return,讓function外,可以取出內變數
}
aFun.a='function物件屬性';
console.log(`aFun.a= ${aFun.a}`) // aFun.a= function物件屬性
console.log(`aFun return a= ${aFun()}`); //aFun return a= function內變數
小結論:
function scope
console.log(a);
fun();
console.log('----------')
function fun(){
console.log(b)
var b=2;
}
var a=1;
var a; //初始化undefined
function fun(){
var b //初始化undefined
console.log(b)
b=2;
}
console.log(a); //undefined
fun(); //undefined
console.log('----------')
a=1;
console.log(a); //1
var a='全域a';
console.log(`a=${a}`)
console.log(`a=${fun('實參')}`)
outerfun();
fun1();
function outerfun(){
a='在outerfun中改a值'
var a='outterfun a'
for(var a=0;a<5;a++){
console.log(`a=${a}`?)
a='for loop裡面的a'
console.log(`a=${a}`)
}
console.log(`a=${a}`);
function innerfun(){
console.log(`a=${a}`);
}
innerfun();
}
function fun(a){
return a;
}
function fun1(){
a='在fun1中改a值'
}
console.log(`a=${a}`)
小提醒:變數
前面沒寫var
,要嘛是引用自己或是引用外層的變數,
要嘛就是新建全域變數,但這種不會提升
.
.
.
.
.
.
.
.
.
.
.
a=全域a
a=實參
a=0
a=for loop裡面的a
a=NaN
a=NaN
a=在fun1中改a值
//模擬:for迴圈裡的a
var num='我是字串,我要先被加1,再被轉成number'
num+=1 //'我是字串,我要先被加1,再被轉成number1'
num =Number(num) //string轉number
console.log(num) //NaN
console.log(typeof num) //number
//模擬:判斷是否離開for迴圈
//句型:(判斷句)?true執行:fales執行
console.log((NaN<5)?'yes':'no') //no,離開for迴圈
a在各個function scope中,被改值的過程