摘要:預(yù)解析聲明告知瀏覽器在全局作用域中有一個變量名為的變量。執(zhí)行代碼的就是棧內(nèi)存,作用域也是棧內(nèi)存。關(guān)鍵字在中主要研究都是函數(shù)中的中的代表的是當(dāng)前行為執(zhí)行的主體方法,函數(shù),事件中的上下文代表的是當(dāng)前行為執(zhí)行的環(huán)境區(qū)域例如小明在沙縣小吃吃蛋炒飯。
基本認(rèn)識
數(shù)據(jù)類型
基本數(shù)據(jù)類型
string, number, null, boolean, undefined
引用數(shù)據(jù)類型
object: [],{},/d/,Date
function
函數(shù)類型
開辟內(nèi)存空間
把函數(shù)中的代碼當(dāng)作字符串先存儲
把內(nèi)存地址復(fù)制給當(dāng)前函數(shù)名
JS引擎
當(dāng)瀏覽器加載HTML頁面時候,首先會先提供一個供全局JS代碼執(zhí)行的環(huán)境 --> 全局作用域 (global、window)
函數(shù)先把代碼體當(dāng)作字符串,存儲到堆內(nèi)存,引用賦值給當(dāng)前函數(shù)名。
執(zhí)行會開辟棧,來執(zhí)行當(dāng)前代碼。
聲明declare:告知瀏覽器在全局作用域中有一個 變量名 為 xxx 的變量。(如果一個變量只是聲明了但是沒有賦值,默認(rèn)值:undefind)
定義defined:對變量進(jìn)行賦值
預(yù)解析
在當(dāng)前的作用域中,JS代碼執(zhí)行之前,瀏覽器首先會默認(rèn)的把所有的帶var,和function的進(jìn)行提前的聲明或定義
var 和 function 關(guān)鍵字
對于帶var 和 function 關(guān)鍵字的在預(yù)解析的時候操作
var -> 在預(yù)解析的時候只是提前聲明了
function -> 在預(yù)解析的時候提前的聲明了 + 定義 都完成了。
預(yù)解析只發(fā)生在當(dāng)前的作用域下進(jìn)行解析。
一開始只會對widnow環(huán)境下的進(jìn)行預(yù)解析,只有函數(shù)執(zhí)行的時候才會對函數(shù)中的進(jìn)行解析
JS內(nèi)存的分類
根據(jù)作用分類
棧內(nèi)存: 用來提供一個供JS代碼執(zhí)行的環(huán)境 --> 作用域 (全局作用域/私有的作用域,和函數(shù))
堆內(nèi)存: 用來存儲引用數(shù)據(jù)類型的值 --> 對象存儲的是屬性名和屬性值,函數(shù)存儲的是代碼字符串
區(qū)分私有變量和全局變量
在全局作用域下聲明(預(yù)解析的時候)的變量是全局變量
在私有作用域中聲明的變量和函數(shù)形參都是私有變量.
在私有作用域中,代碼執(zhí)行的時候遇到了一個變量,首先需要確定是否為私有變量,如果是私有變量,那么和外面的作用域沒有任何關(guān)系;
函數(shù)執(zhí)行
當(dāng)函數(shù)執(zhí)行的時候(直接目的:讓函數(shù)體中的代碼執(zhí)行),首先會形成一個新的私有作用域。
執(zhí)行代碼的就是棧內(nèi)存,作用域也是棧內(nèi)存。
如果有形參,先給形成賦值
進(jìn)行私有作用域預(yù)解析
私有作用域的代碼從上至下執(zhí)行
函數(shù)形成一個新的私有作用域保護(hù)了里面的私有變量不受外界的干擾。(外邊變量修改不了私有變量的,私有變量的也修改不了外邊變量)
作用域鏈
如果不是私有變量,則往當(dāng)前的上級作用域進(jìn)行查找,如果上級沒有則繼續(xù)查找,則一直找到頂級作用域(window)。
全局變量的細(xì)節(jié)在全局作用域中,帶var和不帶var的關(guān)系
區(qū)別:帶var的可以進(jìn)行預(yù)解析,所以在賦值的前面執(zhí)行不會報錯;
不帶var的是不能進(jìn)行預(yù)解析的,在前面使用該變量名會報錯。
場景在全局作用域下,帶var和不帶var的關(guān)系:
console.log(num); // undefiend var num = 10;
console.log(num2); // 報錯 num2 = 10;
關(guān)系:先判斷是否是全局變量,如果是就輸出,如果不是會再去判斷是否是window底下的屬性。
num2=10; --> 相當(dāng)于給window增加了一個叫做num2的屬性名,屬性值是10
var num=10; --> 首先它相當(dāng)于給全局作用域增加了一個全局變量num,但是不僅如此,也相當(dāng)于給window增加了一個屬性num,屬性值10
var num = 10; console.log(num); // 10 console.log(window.num); // 10 num2 = 10; console.log(num2); // 10 // window.num2 console.log(window.num2); // 10
第一種:
function fn() { console.log(total); // 報錯 total = 100; } fn(); console.log(total); // 100
第二種:
function fn() { total = 100; } fn(); console.log(total); // 100
私有作用域中出現(xiàn)的一個變量不是私有的,則往上級作用域進(jìn)行查找,上級沒有則繼續(xù)向上尋找,一直找到window為止,如果window下也沒有,分為兩種情況:
獲取值:console.log(total); --> 報錯(JS中,如果在不進(jìn)行任何特殊處理的情況下,報錯之后,代碼退出執(zhí)行)
設(shè)置值: total = 100; --> 相當(dāng)于給window增加了一個屬性名total,屬性值為100
預(yù)解析機制in操作符:"num" in window 判斷num是否為window這個對象的一個屬性,是的話返回true,不是返回false
預(yù)解析的時候不管你的條件是否成立,都要把帶var的進(jìn)行提前聲明
if (!("num" in window)) { // 預(yù)解析,var num --> window.num // "num" in window 為true var num = 12; } console.log(num); // undefined
函數(shù)表達(dá)式
匿名函數(shù)表達(dá)式:把函數(shù)定義的部分當(dāng)作一個值賦值給變量/元素.
fn(); // 報錯 var fn = function() { // 匿名函數(shù)之函數(shù)表達(dá)式 // 把函數(shù)定義的部分當(dāng)作一個值賦給變量/元素的某一個事件 console.log("ok"); } fn(); // ok fn(); // ok function fn() { console.log("ok"); } fn(); // ok
自執(zhí)行函數(shù)
自執(zhí)行函數(shù):定義和執(zhí)行一起完成
自執(zhí)行函數(shù)在全局作用域下不進(jìn)行預(yù)解析,當(dāng)代碼執(zhí)行到當(dāng)前位置的時候定義和執(zhí)行一起完成了。
(function(num) {})(100); ~function(num) {}(100); !function(num) {}(100); +function(num) {}(100); !function(num) {}(100);
return 后續(xù)的語句
函數(shù)體中reutrn后續(xù)的代碼雖然不在執(zhí)行了,但是需要進(jìn)行預(yù)解析。
return 的函數(shù)是返回值,并不需要預(yù)解析。
function fn() { console.log(num); // undefined return function () { console.log(this); } // return 跟著的語句不會預(yù)解析 var num = 100; // var 進(jìn)行預(yù)解析 } var t = fn(); console.log(t());
函數(shù)權(quán)重高
在JS中如果變量名和函數(shù)名重復(fù),是沖突。函數(shù)級別高,使用的是函數(shù)。
console.log(fn); function fn() { } var fn = 10;
在預(yù)解析的時候,如果名字已經(jīng)聲明過了,不需要重新聲明,但是需要重新賦值.
// 聲明 + 定義: fn: oxfff11 // 聲明:var fn;(不需要重新聲明) // 聲明 + 定義: fn: oxfff222 // ---> fn: oxfff222 fn(); // 2 function fn() {console.log(1);} fn(); // 2 var fn = 10; // 修改作用域值 fn(); // 報錯 function fn() {console.log(2);} fn(); // 停止執(zhí)行查找作用域
如何查找當(dāng)前作用域的上級作用域
看當(dāng)前函數(shù)是在哪個作用域下定義的,那么它的上級作用域就是誰。(和函數(shù)在哪里執(zhí)行的沒有任何的關(guān)系)
函數(shù)作用域,查詢變量,定義的位置有關(guān).
var num = 12; function fn() { var num = 120; return function() { console.log(num); } } var f = fn(); f(); // 120 // window環(huán)境下執(zhí)行,先找父級,后找window // 匿名函數(shù)也是堆內(nèi)存。 ~function() { var num = 111; f(); }();內(nèi)存釋放&作用域銷毀
堆內(nèi)存釋放
堆內(nèi)存作用:存放引用內(nèi)存的屬性值
釋放方法:null空對象指針
對象數(shù)據(jù)類型或者函數(shù)數(shù)據(jù)類型在定義的時候首先都會開辟一個堆內(nèi)存,
堆內(nèi)存有一個引用的地址,如果外邊有變量知道了這個地址,這個內(nèi)存就被占用,不能銷毀。
var obj1 = {name: 1}; var obj2 = obj1; // 想讓堆內(nèi)存釋放/銷毀,只需要把所有的引用它的變量賦值為null即可。如果堆內(nèi)存沒有任何東西被占用了,那么瀏覽器會在空閑的時候,會把它銷毀。 // 垃圾回收 obj1 = null; obj2 = null;
棧內(nèi)存釋放或作用域銷毀
棧內(nèi)存作用:存放作用域
作用域:
全局作用域(瀏覽器天然開辟,瀏覽器關(guān)閉的時候才釋放)
私有作用域(只有函數(shù)執(zhí)行,才會產(chǎn)生私有做作用域)
銷毀情況
一般情況下,函數(shù)執(zhí)行會形成一個新的私有的作用域,當(dāng)私有作用域中的代碼執(zhí)行完成后,當(dāng)前作用域都會主動進(jìn)行釋放和銷毀。
作用域有被子級作用域引用,父級的私有變量不能銷毀。
函數(shù)執(zhí)行返回了一個引用數(shù)據(jù)類型值,并且在函數(shù)外邊一個變量接收,這種情況下一般形成的私有作用域都不能被銷毀。(閉包)
在一個私有的作用域中,給DOM元素的事件綁定方法,一般情況下,私有作用域都不會銷毀。( DOM對象,在執(zhí)行性函數(shù)中被引用)
返回的回調(diào)函數(shù)再次被執(zhí)行,不會被立即銷毀內(nèi)存 (不立即銷毀)
// 1: 引用類型的返回值,被外界引用 function fn() { var num = 10; return function() { } } var f = fn(); // 2: DOM對象,在執(zhí)行性函數(shù)中被引用 var oDiv = document.getElementById("div1"); ~function() { oDiv.onclick = function() {} }(); // 當(dāng)自執(zhí)行函數(shù)形成的這個私有作用域也不銷毀 // 3: 返回的回調(diào)函數(shù)再次被執(zhí)行,不會被立即銷毀內(nèi)存 (不立即銷毀) function fn() { var num = 10; return function() { } } fn()(); // 首先fn執(zhí)行,返回一個回調(diào)函數(shù)對應(yīng)的內(nèi)存地址,然后緊接著讓返回的小函數(shù)再執(zhí)行。 // 返回的回調(diào)函數(shù)再次被執(zhí)行,不會被立即銷毀內(nèi)存,當(dāng)返回的回調(diào)函數(shù)執(zhí)行完成后,瀏覽器會在空閑的時候銷毀。
function fn() { var i = 10; return function(n) { console.log(n + (++i)); } } var f = fn(); f(10); // 21 f(20); // 32 fn()(10); // 21 fn()(20); // 31This關(guān)鍵字
在JS中主要研究都是函數(shù)中的this
JS中的this代表的是當(dāng)前行為執(zhí)行的主體(方法,函數(shù),事件...)
JS中的上下文(context)代表的是當(dāng)前行為執(zhí)行的環(huán)境(區(qū)域)
例如: 小明在沙縣小吃吃蛋炒飯。 this->小明 ,context->沙縣小吃
小明可以在沙縣小吃吃,也可以在其他地方吃。上下文環(huán)境可以變化。而吃的主體小明是不變的。
this和context是沒有必然聯(lián)系。
this是誰,和函數(shù)在哪里定義,在哪里執(zhí)行都沒有任何的關(guān)系。和執(zhí)行主體有關(guān)系。
如何判斷執(zhí)行主體?
函數(shù)執(zhí)行,首先看函數(shù)名前面是否有.,有的話,.前面是誰,this就是誰;沒有的話this就是window
function fn() { console.log(this); } var obj = { fn: fn } fn(); // fn中的this, window obj.fn(); // fn中的this, obj function sum() { fn(); // fn中的this,window }; sum(); var o = { sum: function() { fn(); // fn中的this,window } } o.sum();
自執(zhí)行函數(shù)中的this,指代window
給元素的某一事件綁定方法,當(dāng)事件觸發(fā)的時候,執(zhí)行對應(yīng)的方法,方法中的this是當(dāng)前的元素.
document.getElementById("div1").onclick = function() { console.log(this); // 當(dāng)前DOM對象 }
var num = 20; var obj = { num: 30, fn: (function(num) { this.num *= 3; num += 15; return function() { this.num *= 4; num += 20; console.log(num); } })(num) }; var fn = obj.fn; fn(); // window,// 60 * 4 // 35 += 20 // 55 obj.fn(); // 75 console.log(window.num, obj.num); // 240, 120
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/88261.html
摘要:不包括作為其嵌套函數(shù)的被解析的源代碼。作用域鏈當(dāng)代碼在一個環(huán)境中執(zhí)行時,會創(chuàng)建變量對象的一個作用域鏈。棧結(jié)構(gòu)最頂層的執(zhí)行環(huán)境稱為當(dāng)前運行的執(zhí)行環(huán)境,最底層是全局執(zhí)行環(huán)境。無限制函數(shù)上下文?;蛘邟伋霎惓M顺鲆粋€執(zhí)行環(huán)境。 前言 其實規(guī)范這東西不是給人看的,它更多的是給語言實現(xiàn)者提供參考。但是當(dāng)碰到問題找不到答案時,規(guī)范往往能提供想要的答案 。偶爾讀一下能夠帶來很大的啟發(fā)和思考,如果只讀一...
摘要:然而事實上并不是。函數(shù)本身也是一個對象,但是給這個對象添加屬性并不能影響。一圖勝千言作者給出的解決方案,沒有麻煩的,沒有虛偽的,沒有混淆視線的,原型鏈連接不再赤裸裸。所以是這樣的一個函數(shù)以為構(gòu)造函數(shù),為原型。 注意:本文章是個人《You Don’t Know JS》的讀書筆記。在看backbone源碼的時候看到這么一小段,看上去很小,其實忽略了也沒有太大理解的問題。但是不知道為什么,我...
摘要:理解的函數(shù)基礎(chǔ)要搞好深入淺出原型使用原型模型,雖然這經(jīng)常被當(dāng)作缺點提及,但是只要善于運用,其實基于原型的繼承模型比傳統(tǒng)的類繼承還要強大。中文指南基本操作指南二繼續(xù)熟悉的幾對方法,包括,,。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。 怎樣使用 this 因為本人屬于偽前端,因此文中只看懂了 8 成左右,希望能夠給大家?guī)韼椭?...(據(jù)說是阿里的前端妹子寫的) this 的值到底...
在過往學(xué)習(xí)的JavaScript都是在基礎(chǔ),現(xiàn)在為大家介紹更為深入的JavaScript知識。 JavaScript函數(shù) JavaScript函數(shù)和Java函數(shù)是有一部分相似的,所以學(xué)習(xí)起來也會相對簡單 基本構(gòu)造 1.直接構(gòu)造 //function代表函數(shù)標(biāo)志,name為函數(shù)名稱,參數(shù)可有可無 functionname(參數(shù)){ //... return; } 2....
摘要:捕獲所有參數(shù)綁定當(dāng)一個函數(shù)用作構(gòu)造函數(shù)時使用關(guān)鍵字,它的被綁定到正在構(gòu)造的新對象。使用來調(diào)用函數(shù),或者說發(fā)生構(gòu)造函數(shù)調(diào)用時,會自動執(zhí)行下面的操作你不知道的創(chuàng)建或者說構(gòu)造一個全新的對象。在箭頭函數(shù)中,與封閉詞法上下文的保持一致。 this 實際上是在函數(shù)被調(diào)用時發(fā)生的綁定,它指向什么完全取決于函數(shù)的調(diào)用位置(也就是函數(shù)的調(diào)用方法)。 四條規(guī)則:(你不知道的JS) 1. 默認(rèn)綁定 func...
閱讀 1760·2023-04-26 00:20
閱讀 1804·2021-11-08 13:21
閱讀 1930·2021-09-10 10:51
閱讀 1557·2021-09-10 10:50
閱讀 3249·2019-08-30 15:54
閱讀 2131·2019-08-30 14:22
閱讀 1429·2019-08-29 16:10
閱讀 3089·2019-08-26 11:50