課時1:預解釋
JS中的數據類型
number、string、 boolean、null、undefined
JS中引用數據類型
object: {}、[]、/^$/、Date?
Function
var num=12; var obj={name:'白鳥齊鳴',age:10}; function fn(){ console.log('勿忘初心方得始終!') }console.log(fn);//把整個函數定義部分(函數本身)在控制臺輸出 console.log(fn());//把當前函數返回的結果(return后面寫的是啥,返回值就是啥,如果沒有return,默認返回值是undefined);
window全局作用域:
1、當瀏覽器加載HTML頁面的時候,首先會提供一個全局JS代碼執行的環境–>全局作用域(global / window)
2、預解釋(變量提升)
在當前的作用域中,JS代碼執行之前,瀏覽器首先會默認的把所有帶var 、function的進行提前的聲明或者定義
1)理解聲明和定義
var num=12;
聲明(declare):var num;->告訴瀏覽器在全局作用域中有一個num的變量了,如果一個變量只是聲明了但是沒有賦值,默認的值是undefined
定義(defined):num=12; ->給我們的變量進行賦值
2)對于帶var和function關鍵字的在預解釋的時候操作還是不一樣的
var -> 在預解釋的時候只是提前的聲明
function -> 在預解釋的時候提前的聲明+定義都完成了
3)預解釋只發生在當前的作用域下,例如:開始只對window下的進行預解釋,只有函數執行的時候才會對函中的進行預解釋
console.log(num);//undefined var num=12; console.log(num);//12var obj={name:'白鳥齊鳴',age:100 }fn(100,200);//可以在上面執行,因為在預解釋的時候聲明+定義已經完成了 function fn(num1,num2){var total=num1+num2;console.log(total); }
3、JS中內存的分類
棧內存:用來提供一個供JS代碼執行的環境 –> 作用域(全局作用域、私有作用域)
堆內存:用來存儲引用數據類型的值 -> 對象存儲的是屬性名和屬性值,函數存儲的是代碼字符串…

課時2: 作用域鏈
1、如何區分私有變量和全局變量?
1) 在全局作用域下聲明(預解釋的時候)的變量是全局變量?
2) 在“私有作用域中聲明的變量”和“函數的形參”都是私有變量;?
在私有作用域中,我們代碼執行的時候遇到了一個變量,首先我們需要確定它是否為私有的變量,如果是私有的變量,那么和外面的任何東西都沒有關系;如果不是私有,則往當前作用域的上級作用域進行查找,如果上級作用域也沒有則繼續查找,一直找到window為止……作用域鏈2、當函數執行的時候(直接目的:讓函數體中的代碼執行),首先會形成一個私有的作用域,然后按照如下的步驟執行
1)如果有形參,先給形參賦值?
2)進行私有作用域中的預解釋?
3)私有作用中的代碼從上到下執行?
……?
函數形成一個新的私有作用域保護了里面的私有變量不受外界的干擾(外面修改不了私有的,私有的也修改不了外面的)–>閉包
console.log(total);//undefined var total=0; function fn(num1,num2){console.log(total); //undefinedvar total=num1+num2;console.log(total);//300 } fn(100,200); console.log(total);//0
console.log(total);//undefined var total=0; function fn(num1,num2){console.log(total); //total不是私有的,找全局下的total,也就是在這里出現的所有的total其實應該都是全局->0total=num1+num2; //全局的total=300console.log(total);//300 } fn(100,200); console.log(total);//300
課時3:全局變量的細節問題
在全局作用域中,帶var 和不帶var的關系??
區別:帶var的可以進行預解釋,所以在賦值的前面執行不會報錯;不帶var的是不能進行預解釋的,在前面執行會報錯:
console.log(num);//undefined var num=12; console.log(num2);//報錯;num2 is not defined,不執行下面 num2=13; console.log(num2);
關系:num2=12 –>相當于給window增加了一個叫做num2的屬性名,屬性值是12?
var num=12;–>首先它相當于給全局作用域增加了一個全局變量num,但是不僅如此,它也相當于給window增加了一個屬性名num2,屬性值是12
console.log(num);//undefined var num=12; console.log(num);//12 num2=13; console.log(num2);//13-->window.num2
第一種: var total=0; function fn(){console.log(total);//undefinedvar total=100; } fn(); console.log(total);//0 第二種: var total=0; function fn(){console.log(total);//0total=100; } fn(); console.log(total);//100 第三種: 私有作用域中出現了一個變量不是私有的,則向上級作用域進行查找,上級沒有則繼續向上查找,一直找到window為止,如果window下也沒有呢? 我們是獲取值:console.log(total);-->報錯 我們是設置值: total=100;->相當于給window增加了一個屬性名total,屬性值100 function fn(){//console.log(total);//total is not definedtotal=100; } fn(); console.log(total);//100;window.total=100; JS中如果在不進行任何特殊處理的情況下,上面的代碼報錯,下面的代碼都不在執行了
課時4:預解釋是一種毫無節操的機制
預解釋是毫無節操的一種機制?
自從學了預解釋,從此節操是路人?
in:”num” in window 判斷num是否為window這個對象的一個屬性,是的話返回true,不是的話返回false
1、預解釋的時候不管你的條件是否成立,都要把帶var的進行提前聲明window的預解釋:var num;-->window.num;if(!('num' in window)){//'num' in window ->true->取反是false var num=12; } console.log(num);//undefined2、預解釋的時候只預解釋"="左邊的,右邊的是值,不參與預解釋 匿名函數之函數表達式:把函數定義的部分當做一個值賦值給我們的變量/元素的某一個事件 window下的預解釋:var fn;fn();//fn is not a function var fn=function (){console.log('OK');}fn();//OK;函數聲明+定義完成 function fn(){console.log('OK'); } fn();//OK3、自治行函數定義的那個function在全局作用域下不進行預解釋,當代碼執行到這個位置的時候定義和執行一起完成了 自執行函數:定義和執行一起完成了(function (num){})(100); ~function (num){}(100); +function (num){}(100); -function (num){}(100); !function (num){}(100);4、函數體中return下面的代碼雖然不在執行了,但是需要進行預解釋;return后面跟著的都是我們返回的值,所以不進行預解釋function fn(){ //預解釋:var num; console.log(num);//undefinedreturn function (){ }var num=100; }; fn();5、如果在預解釋的時候,如果名字已經聲明過了,不需要從新的聲明,但是需要新的賦值; 在JS中如果變量的名字和函數的名字重復了,也算沖突 預解釋:var fn; window.fn; fn=xxxfff000 window.fn=xxxfff000var fn=13; function fn(){ console.log('OK'); }window預解釋: 聲明+定義 fn=xxxfff111 聲明 var fn;(不需要重新聲明) 聲明(不重復進行)+定義 fn=xxxfff222 -> fn=xxxfff222 fn();//2 function fn(){console.log(1);} fn();//2 var fn=10;//fn=10 fn();//fn() ERROR:fn is not a function,以下不執行 function fn(){cosole.log(2);} fn();
課時5:如何查找上級作用域
如何查找當前作用域的上一級作用域??
看當前函數是在哪個作用域下定義的,那么它的上級作用域就是誰 –> 和函數在哪執行的沒有任何的關系
var num=12; function fn(){var num=120;return function (){console.log(num);//120 } } var f=fn(); f()~function (){var num=1200;f();//120 }()
課時6:關于內存釋放和作用域銷毀的研究
堆內存?
對象數據類型或者函數數據類型在定義的時候首先會開辟一個堆內存,堆內存有一個引用的地址,如果外面有變量等知道了這個地址,我們就說這個內存被占用了,就不能銷毀了
var obj1={name:'張三'}; var obj2=obj1;我們想要讓堆內存釋放/銷毀,只需要把所有引用它的變量值賦值為null即可,如果當前的堆內存沒有任何東西被占用了,那么瀏覽器會在空閑的時候把它銷毀.... obj1=null; obj2=null;
棧內存
1)全局作用 (棧內存)?
只有當頁面關閉的時候全局作用域才會銷毀2)私有作用域(只有函數執行會產生私有作用域) (堆內存)?
一般情況下,函數執行會形成一個新的私有作用域,當私有作用域中的代碼執行完成后,我們當前作用域都會主動的進行釋放和銷毀但是還是存在特殊情況的:
當前私有作用域中的部分內存被作用域以外的東西占用了,那么當前的這個作用域就不能銷毀了?
a、函數執行返回了一個引用數據類型的值,并且在函數的外面被一個其他的東西給接收了,這種情況下一般形成的私有作用域都不會銷毀
function fn(){ var num=100; return function(){ } } var f=fn(); 解析: 返回的是一個函數 為引用數據類型
b、在一個私有的作用域中,給DOM元素的事件綁定方法,一般情況下我們的私有作用域都不銷毀
var oDiv=document.getElementById('div1'); ~function (){oDiv.onclick=function (){} }()//當前自執行函數也不銷毀
c、下述情況屬于不立即銷毀->fn返回的函數沒有被其他的東西占用,但是還需要執行一次呢,所以暫時不銷毀,當返回的值執行完畢后,瀏覽器會在空閑的時候銷毀了–>’不立即銷毀’
function fn(){ var num=100; return function (){} } fn()(); //首先執行fn,返回一個小函數對應的內存地址,然后緊接著讓返回的小函數在執行
課時7:作用域練習題
++i和i++?
都是自身累加1,在和其他的值進行運算的時候是有區別的?
i++:先拿i的值進行運算,運算完成本身在加1?
++i:先本身累加1,然后拿累加完成的結果去運算
var i=5;//console.log(1+i++)//6 i=6//console.log(1+(++i))//i=6 7console.log(2+(i++)+(++i)+(++i)+(i++));//30cosnle.log(i);//9
function fn(){var i=10;return function (n){console.log(n+(++i));} } var f=fn(); f(10);//21 i=11 f(20);//32 i=11+1 fn()(10);//21 i=11 新作用域 fn()(20);//31 i=11 新作用域
function fn(i){return function (n){console.log(n+i++) } } var f=fn(13); f(12);//25 f(14);//28 fn(15)(12);//27 fn(16)(13);//29
課時8:this關鍵字
我們在JS中主要研究的都是函數中的this?
JS中的this代表的是當前行為執行的主體:JS中的context代表的是當前行為執行的環境(區域):
this是誰和函數在哪定義的和在哪執行的都沒有任何關系:如何的區分this呢?
1、函數執行,首先看函數名前面是否有” . “,有的話” . “前面是誰this就是誰;沒有的話this就是window
function fn(){ console.log(this); } var obj={fn:fn}; fn();//this-->window obj.fn()//this-->obj
function sum(){//this-->windowfn();//this-->window } sum();var oo={sum:function (){//this-->oofn();//this-->window } } oo.sum();
2、 自執行函數中的this永遠是window?
3、給元素的某一個事件綁定方法,當事件觸發的時候,執行對應的方法,方法中的this是當前的元素
function fn(){console.log(this); } var obj={fn:fn}; fn();//this-->window obj.fn();//this-->obj document.getElementById('div1').οnclick=fn;//fn 中的this是div1 document.getElementById('div1').οnclick=function (){//this-->#div1fn();// this-->window };
4、 在構造函數模式中,類中(函數體中)出現的this.xxx=xxx中的this是當前類的一個實例
課時9 綜合練習題
var num=20; //20*3=60var obj={num:30,fn:(function (num){this.num*=3;//num=60num+=15; //85var num=45;return function (){this.num*=4;//240num+=20; console.log(num); }})(num)// --> 把全局變量num的值20賦值給了自執行函數的形參,而不是obj下的30,如果想是obj下的30,我們需要寫obj.num };var fn=obj.fn;fn();//65obj.fn();//65+20=85console.log(window.num,obj.num);//240 120
?