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