1、變量名區(qū)分大小寫; 注意代碼塊的概念。
變量分為原始值和引用值:原始值存儲在棧,引用值存儲在堆(引用值一般是一個指針或?qū)ο竺?、函?shù)名)。在C語言中編譯的程序占用的內(nèi)存分為以下幾個部分:棧區(qū)(由系統(tǒng)分配/內(nèi)存塊連續(xù))、堆區(qū)(由程序員分配與釋放或系統(tǒng)結(jié)束后釋放/鏈表結(jié)構(gòu)不連續(xù)的內(nèi)存塊)、全局區(qū)、文字常量區(qū)、程序代碼。
(1)原始類型有5種:Undefined、Null、Boolean、Number、String
Null專用值為null表示尚存在的對象,Undefined申明變量未初始化賦予該值(不等同于未定義的值,typeof無法區(qū)分是未聲明還是未初始化)
成都創(chuàng)新互聯(lián)公司于2013年成立,是專業(yè)互聯(lián)網(wǎng)技術(shù)服務公司,擁有項目成都網(wǎng)站設計、成都網(wǎng)站制作網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元靈川做網(wǎng)站,已為上家服務,為靈川各地企業(yè)和個人服務,聯(lián)系電話:18982081108
var oTemp;
typeof(oTemp);
console.log(oTemp == undefined);
結(jié)果為:
Hello
undefined
true
如果直接未聲明使用oTemp ==undefined程序報錯,null ==undefined是true說明兩值相等,但是不代表含義相同。
Infinity表示無窮大,往往用isFinite()方法確保該數(shù)不是無窮大。還有一個特殊值是NaN,表示非數(shù),不用使用NaN==NaN(輸出false)判單非數(shù),使用isNaN()判斷非數(shù)。
console.log(NaN ==NaN);
var i=123;
console.log(isNaN(i)+'+++++++'+isNaN(a));
結(jié)果為:
false
false+++++++true
Number可以為32位整數(shù)也可以為64位浮點數(shù),String大小是沒有固定的
(2)引用類型通常叫做class,遇到引用值也就是處理對象。ECMAScript中其實沒有類這個詞,主要用對象定義,等同其他語言的類概念。
(3)以js舉例:JavaScript的執(zhí)行上下文生成之后,會創(chuàng)建一個叫做變量對象的特殊對象,基礎(chǔ)數(shù)據(jù)類型往往都會保存在變量對象中,引用數(shù)據(jù)類型的值是保存在堆內(nèi)存中的對象。JavaScript不允許直接訪問堆內(nèi)存數(shù)據(jù),需要通過地址引用訪問(操作地址值指向堆內(nèi)存空間數(shù)據(jù)訪問),如下代碼:
var a = 10;
var b = a;
b = 100;
console.log(a); //a=10 a、b是兩個獨立的變量空間,相互不干擾
再看:
var a= { m: 10, n: 20 }
var b = a;
b. m= 15;
console.log(a.m); //輸出15 a、b兩個不同空間變量指向同一個地址引用
2、函數(shù)聲明整體提升,變量的聲明提升到(一種理解得比較形象好記憶的方式,并非本質(zhì)原理,原理參考3)。
沒有聲明或直接賦值的變量會報錯:
console.log(a) //error
后面的變量聲明會提前到最前面
console.log(global); // undefined
var global = 'global';
console.log(global); // globalfunction fn () {
console.log(a); // undefined
var a = 'aaa';
console.log(a); // aaa
}
fn();
var聲明的變量,內(nèi)層變量可能會覆蓋外層變量,外層變量會作用的內(nèi)層;js中未經(jīng)聲明的變量歸window所有;js中全局變量都歸window所有。
var tmp = new Date();
function f() {
console.log(tmp);
if (false) {
var tmp = 'hello world';
}
}f(); // undefined
函數(shù)聲明有兩種:函數(shù)聲明式、函數(shù)字面量式(因為var定義的),后者無法函數(shù)提升,如下:
console.log(f1); // function f1() {}
console.log(f2); // undefined
function f1() {}
var f2 = function() {}
3、在程序執(zhí)行前的預編譯中(執(zhí)行上下文代碼執(zhí)行過程),一共有4個過程要完成:
(1)創(chuàng)建active object(OA)
(2)找形參和變量聲明,將形參和變量聲明做為OA的屬性名,屬性值為Undefine(此步就是變量提升的本質(zhì))
(3)將實參和形參統(tǒng)一
(4)在函數(shù)體中找函數(shù)聲明,值賦予函數(shù)體
變量作用域要理解執(zhí)行上下文的過程:創(chuàng)建變量對象、執(zhí)行(變量賦值、函數(shù)引用、其他代碼)。其中創(chuàng)建分三個步驟:創(chuàng)建arguments對象,檢查function聲明創(chuàng)建屬性,檢查Var變量聲明創(chuàng)建屬性。
1 var a = 10;
2 function aaa(){//step-4
3 alert(a);//step-5->執(zhí)行alert,此時只能找到外面的a=10故彈框10
4 }
5 function bbb(){//step-2
6 var a = 20;
7 aaa();//step-3
8 }
9 //定義了函數(shù)沒啥用,調(diào)用才是真格的所以這里是step-1
10 bbb();
作用域總結(jié):
(1)ES6之前的js沒有塊級作用域(你可以自己閉包或其他方法實現(xiàn)),只有函數(shù)級作用域,函數(shù)外面的變量函數(shù)里面可以找到,函數(shù)里面的變量外面找不到
(2) 變量的查找是就近原則,去尋找var定義的變量,當就近沒有找到的時候就去查找外層。函數(shù)聲明比var聲明要優(yōu)先。
(3)當參數(shù)跟局部變量重名時,優(yōu)先級是等同的。傳參時,基本類型傳值,引用類型傳引用。
(4) 理解執(zhí)行上下文:每個函數(shù)執(zhí)行時產(chǎn)生執(zhí)行上下文(EC),一個執(zhí)行上下文定義了一個函數(shù)執(zhí)行環(huán)境。
4、立即執(zhí)行函數(shù)(自執(zhí)行函數(shù))的理解:
先說說如下函數(shù)的執(zhí)行過程,聲明函數(shù)式makeCounter(),內(nèi)部定義變量i,返回一個函數(shù)體,該函數(shù)體區(qū)塊變量i和被返回到的函數(shù)體makeCounter中i存儲地址一致,直接上代碼比較結(jié)果分析(這里有點難理解):
function makeCounter() {
// i只是makeCounter函數(shù)內(nèi)的局部變量
var i = 0;return function() {
console.log( ++i );
};
}
console.log("1----"+makeCounter().toString());
console.log("2----"+(makeCounter())());
console.log("3----"+makeCounter.toString());
console.log("4----"+parseInt(makeCounter()));
var a=makeCounter();
console.log("5----"+a);
a();
顯示結(jié)果如下:
1----function () {
console.log(++i);
}
1 //注意這個結(jié)果,是由步驟2中console.log產(chǎn)生
2----undefined
3----function makeCounter() {
// i只是makeCounter函數(shù)內(nèi)的局部變量
var i = 0;
return function () {
console.log(++i);
};
}
4----NaN
5----function () {
console.log(++i);
}
1
下面說明下為什么最后console.log的不同結(jié)果:
**每次當控制器轉(zhuǎn)到可執(zhí)行代碼的時候,就會進入一個執(zhí)行上下文。執(zhí)行上下文可以理解為當前代碼的執(zhí)行環(huán)境,它會形成一個作用域。JavaScript中的運行環(huán)境大概包括三種情況:全局環(huán)境(JavaScript代碼運行起來會首先進入該環(huán)境)、函數(shù)環(huán)境(當函數(shù)被調(diào)用執(zhí)行時,會進入當前函數(shù)中執(zhí)行代碼)、eval。
**函數(shù)中,遇到return能直接終止可執(zhí)行代碼的執(zhí)行,因此會直接將當前上下文彈出棧。
(1)console.log("1----"+makeCounter().toString()) 對照1,顯示為function(){..},說明執(zhí)行makeCounter()后函數(shù)體,return了的真正值:一個函數(shù)體
(2)console.log("2----"+(makeCounter())()) 對照顯示數(shù)值1 和 2----undefined,因為函數(shù)體function(){...}后加了(),那么函數(shù)就立即執(zhí)行了,所以打印了1。但是函數(shù)本身是沒有返回值的,所以會顯示undefine()
(3)console.log("3----"+makeCounter.toString()) 僅僅是輸出了這個名為makeCounter函數(shù)體中存儲的函數(shù)式全部代碼內(nèi)容
(4)非數(shù)返回也好理解
(5)同2理解,這里的實例化后然后用()執(zhí)行和2一個道理,唯一不同是沒有console.log(a())
4、立即執(zhí)行函數(shù)的寫法:
// 最常用的兩種寫法
(function(){ / code / }()); // 推薦寫法
(function(){ / code / })();
//與運算符相關(guān)聯(lián)后
var i = function(){ return 10; }();
true && function(){ / code / }();
0, function(){ / code / }();// 一元運算符
!function(){ / code / }();
~function(){ / code / }();
-function(){ / code / }();
+function(){ / code / }();// 你也可以這樣
new function(){ / code / }
new function(){ / code / }() // 帶參數(shù)
6、let增加了塊級的作用,不在同一塊內(nèi)的變量相互不干擾,外層塊無法讀取內(nèi)層塊let定義變量:
function f1() {
let n = 5;
if (true) {
let n = 10;
}
console.log(n); // 5
}
零散的記錄了一些,后面會做梳理