簡單談談javascript中的變數、作用域和記憶體問題_javascript技巧
【變數】
[1]定義:可變的量,相當於給一個不定的資料起了一個外號。變數是儲存資訊的容器。
[2]特性:js中的變數是鬆散類型的,可以保存任何類型的資料。它只是在特定時間用來保存特定值的名字而已。由於不存在定義某個變數必須要保存何種資料類型值的規則,變數的值及其資料類型可以在腳本的生命週期內改變。
[3]變數宣告:變數可以在宣告時賦值,但不能有其他運算,如 =、-=等
var a = 2;//是正确的 var a += 2;//是错误的 var a = 2++;//是错误的,++只能用于变量,不能用于常量
[4]注意:用var運算子定義的變數將成為定義該變數的作用域中的局部變數。若省略var操作符,可以建立一個全域變量,但在嚴格模式下會拋出 ReferenceError錯誤
[5]var:使用var宣告的變數會自動被加入到最接近的環境。如果初始化變數時沒有使用var聲明,則變數會自動被加入到全域環境。在嚴格模式下,初始化未經宣告的變數會導致錯誤。
[6]局部變數:如果局部環境中存在同名標識符,就不會使用位於父環境中的標識符。任何位於局部變數color的宣告之後的程式碼,如果不使用window.color都無法存取全域color變數
【標識符】
[1]定義:變數、函數、屬性的名字,或是函數的參數。
[2]注意:
[2.1]第一個字元必須是一個字母、底線或一個美元符號。其他字元可以是字母、底線、美元符號或數字[不能出現中劃線]
[2.2]標識符中的字母也可以包括拓展的ASCII或Unicode字母字元,可以使用中文
[2.3]識別碼應採用小駝峰格式,第一位應該是資料的類型,常見的標識如下:
数组 a Array aItems 布尔值 b Boolean bIsComplete 浮点数 f FLoat fPrice 函数 fn Function fnHandler 整数 i Integer iItemCount 对象 o Object oDIv1 正则表达式 re RegExp reEmailCheck 字符串 s String sUserName 变量 v Variant vAnything
[2.4]不能把关键字、保留字、true、false和null用作标识符
[2.5]对于不符合标识符命名规则的属性如background-color应写为大括号方式[backgroundColor]
[3]标识符解析:标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级地向后回溯,直到找到标识符为止(如果找不到标识符,表示标识符尚未声明,通常会导致错误发生)。
[3.1]如果局部环境中存在着同名标识符,就不会使用父环境中的标识符
e.g. 全局和局部有同名标识符color,任何位于局部变量color的声明之后的代码,如果不使用window.color都无法访问全局color变量
[3.2]JavaScript引擎在优化标识符查询方面做得不错,访问全局变量和局部变量的时间差别可以忽略不计
【作用域】(也称为执行环境)
[注意]javascript中没有块级作用域
[1]执行环境:执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之相关联的变量对象。环境中定义的所有变量和函数都保存在这个对象中。
[2]全局执行环境:
[2.1]全局执行环境是最外围的一个执行环境,在web浏览器中,全局执行环境被认为是window对象。因此所有全局变量和函数都是作为window对象的属性和方法创建的。全局执行环境直到应用程序退出例如关闭网页或浏览器时才会被销毁
[2.2]一个页面就相当于一个全局作用域。不论是页面中的js代码,还是引用的外部js文件,最终都会按照在页面中的先后依次解析。
[3]函数执行环境:每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中,而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。
[4]作用域链:当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的作用是保证对执行环境有权访问的所有变量和函数的有序访问。作用域的前端始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象。活动对象在最开始时只包含一个变量,即arguments对象(这个对象在全局环境中是不存在的)。作用域链中的下一个变量对象来自包含环境,而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。
[4.1]作用域链的特点:内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。这些环境之间的联系是线性、有次序的。每个环境都可以向上搜索作用域链,以查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入另一个执行环境。
[5]延长作用域链:
[5.1]try-catch语句:catch块会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明
[5.2]with语句:会将指定的对象添加到作用域链中
function buildUrl(){ var qs = '?debug=true'; with(location){ var url = href + qs; } return url; }
【垃圾回收】:javascript具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存。
[1]垃圾回收机制:找出那些不再继续使用的变量,然后释放其占用的内存,垃圾收集器会按照固定的时间间隔,或代码执行中预定的收集时间,周期性地执行这一操作
[2]垃圾收集标记无用变量的两种策略
[2.1]标记清除,标记“进入环境”和“离开环境”。离开作用域的值将被自动标记为可以回收,因此将在垃圾收集期间被删除
[2.2]引用计数,跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1,如果同一个值又被赋给另一个变量,则该值的引用次数加1,相反,如果包含对这个值的引用的变量又取得了另外一个值,则这个值的引用次数减1,当这个值的引用次数为0时,则说明没有办法再访问这个值了,因此就可以将其占用的内存空间回收回来。
[2.2.1]引用计数的问题:循环引用:对象A中包含一个指向对象B的指针,对象B中也包含一个指向对象A的指针
[2.2.2]IE:IE中有一部分对象并不是原生js对象,例如,其BOM和DOM中的对象就是使用c++以COM对象的形式实现,而COM对象的垃圾回收机制采用的就是引用计数策略
var element = document.getElementById('some_element'); var myObject = new Object(); myObject.element = element; element.someObject = myObject;
解决办法:为了避免类似这样的循环引用,最好是在不使用它们的时候手工断开
myObject.element = null;
element.someObject = null;
为了解决此问题,IE9把BOM和DOM对象都转换成了真正的js对象
【内存管理】
[1]主要问题:分配给web浏览器的可用内存数量通常要比分配给桌面应用程序的少,目的是防止运行js的网页耗尽全部系统内存而导致系统崩溃。内在限制问题不仅会影响给变量分配内存,同时还会影响调用栈以及在一个线程中能够同时执行的语句数量
[2]优化方式:为执行中的代码只保存必要的数据。一旦数据不再有用,最好通过将其值设置为null来释放其引用,这种做法叫解除引用。这一做法适用于大多数全局变量和全局对象的属性以及循环引用变量,局部变量会在它们离开执行环境时自动被解除引用。
解除变量的引用并不意味着自动回收该值所占用的内存。解除引用的真正作用是让值脱离执行环境,以便垃圾收集器下次运行时将其回收。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題











typedef struct 在 C 語言中用於建立結構體類型別名,簡化結構體使用。它透過指定結構體別名將一個新的資料類型作為現有結構體的別名。優點包括增強可讀性、程式碼重複使用和類型檢查。注意:在使用別名前必須定義結構體,別名在程式中必須唯一且僅在其宣告的作用域內有效。

Java 中的變數期望值異常可以透過以下方法解決:初始化變數;使用預設值;使用 null 值;使用檢查和賦值;了解局部變數的作用域。

JavaScript 閉包的優點包括維持變數作用域、實作模組化程式碼、延遲執行和事件處理;缺點包括記憶體洩漏、增加了複雜性、效能開銷和作用域鏈影響。

C++ 中的 #include 預處理器指令將外部來源檔案的內容插入到目前原始檔案中,以複製其內容到目前原始檔案的相應位置。主要用於包含頭文件,這些頭文件包含程式碼中所需的聲明,例如 #include <iostream> 是包含標準輸入/輸出函數。

C++智慧指標的生命週期:建立:分配記憶體時建立智慧指標。所有權轉移:透過移動操作轉移所有權。釋放:智慧指標離開作用域或被明確釋放時釋放記憶體。物件銷毀:所指向物件被銷毀時,智慧型指標成為無效指標。

可以。 C++ 允許函數巢狀定義和呼叫。外部函數可定義內建函數,內部函數可在作用域內直接呼叫。巢狀函數增強了封裝性、可重複用性和作用域控制。但內部函數無法直接存取外部函數的局部變量,且傳回值類型需與外部函數宣告一致,內部函數不能自遞歸。

在 Vue 中,let 和 var 宣告變數時在作用域上存在差異:作用域:var 具有全域作用域,let 具有區塊級作用域。區塊級作用域:var 不會建立區塊級作用域,let 建立區塊級作用域。重新宣告:var 允許在同一作用域內重新宣告變數,let 不允許。

JavaScript 中,this 的指向類型有:1. 全域物件;2. 函數呼叫;3. 建構函式呼叫;4. 事件處理程序;5. 箭頭函數(繼承外層 this)。此外,可以使用 bind()、call() 和 apply() 方法明確設定 this 的指向。
