摘要:但對于引用類型的數據主要是對象和數組,變量指向的內存地址,保存的只是一個引用地址指針,只能保證這個引用地址指針是固定的,至于它指向的堆內存中的存儲的值是不是可變的,就完全不能控制了。
基礎概念
變量是存儲信息的容器,這里需要區分一下:變量不是指存儲的信息本身,而是指這個用于存儲信息的容器,可以把變量想象成一個個用來裝東西的紙箱子
變量需要聲明,并且建議在聲明的同時進行初始化,如下所示:
var aa = "1"; let bb = 2; const CC = 3;
如果重新聲明變量,該變量的值不會丟失
var aa = "cc"; var aa; //此時的值還是cc
變量名(標志符)命名要求:
適用于變量/屬性/函數/函數參數的名字等
可由字母、數字、下劃線_及美元符$組成
不可以使用關鍵字、保留字以及true、false、null、(eval、arguments嚴格模式下)
使用undefined雖然不會報錯,但是并不能聲明成功,無論給它初始化為什么,它的值仍然為undefined
最好使用字母開頭(還可以使用_與$)
值類型變量可能包含兩種不同數據類型的值:基本類型值(簡單的數據段)和引用類型值(可能由多個值構成的對象)
因為所有引用類型的值都是Object的實例,所以可以使用 xx instanceof Object 來判斷是否為引用類型的值,如果是則會返回true,否則返回false
存儲方式
基本類型值在內存中占據固定大小空間,因此被保存在棧內存中(棧由操作系統自動分配釋放);
引用類型值是對象,保存在堆內存中;(堆:一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收)
訪問方式
對于基本類型,變量存儲的是具體的值,可以按值訪問,直接操作存儲的值
對于引用類型,變量存儲的是對象引用地址(指針),是按引用訪問,當查詢時,我們需要先從棧中讀取存儲的內存地址,然后再順藤摸瓜地找到保存在堆內存中的值
復制變量值
復制時,基本類型拷貝的是具體的值,而引用類型拷貝的是引用地址,所以引用類型賦值時要格外注意!!!
//基本類型賦值 var num1 = 10; var num2 = num1; console.log(num1,num2);// 10, 10 num2 = 100; console.log(num1,num2);// 10, 100 //引用類型賦值 //person2拷貝了person1的引用地址,所以person1和person2實際上指向的是同一個對象 //所以改變person2會影響到person1 var person1 = { name:"cc" }; var person2 = person1; console.log(person1.name, person2.name);// cc, cc person2.name = "cshine"; console.log(person1.name, person2.name);// cshine, cshine var arr1 = [1,2,3]; var arr2 = arr1; console.log(arr1, arr2);// [1, 2, 3], [1, 2, 3] arr2[1]= "string"; console.log(arr1, arr2);// [1, "string", 3], [1, "string", 3]
傳遞參數
ECMAScript中所有的函數的參數都是按值傳遞,即使是引用類型值的傳遞也是按值傳遞
傳遞基本類型值時,被傳遞的值會被復制給一個局部變量(即命名參數或者arguments中的一個元素)
傳遞引用類型值時,引用類型值是一個引用地址(指針),它也會復制給一個局部變量,這個局部變量再根據這個地址去按引用訪問對象,因此這個局部變量的變化會反映在函數的外部。所以還是按值傳遞,而不是因為它是按引用傳遞才導致局部變量的變化會反映在函數的外部
注意點
es6新增了let和const命令用來聲明變量
let命令,它的用法類似于var,但是所聲明的變量,只在let命令所在的塊級作用域內有效,且在該塊級作用域內不可重復聲明
const聲明一個只讀的常量,一旦聲明,常量的值就不能改變,與let一樣,只在聲明所在的塊級作用域內有效,且在該塊級作用域內不可重復聲明
const實際上保證的,并不是變量的值不得改動,而是變量指向的那個內存地址不得改動。對于簡單類型的數據(數值、字符串、布爾值),值就保存在變量指向的那個內存地址,因此等同于常量。但對于引用類型的數據(主要是對象和數組),變量指向的內存地址,保存的只是一個引用地址(指針),const只能保證這個引用地址(指針)是固定的,至于它指向的堆內存中的存儲的值是不是可變的,就完全不能控制了。因此,將一個對象聲明為常量必須非常小心。
未使用var/let/const進行聲明,此時創建的變量為全局變量,盡量不要這樣做!
var命令和function命令聲明的全局變量,是頂層對象的屬性,let命令、const命令、class命令聲明的全局變量,不屬于頂層對象的屬性(瀏覽器中為window,node中為global)
對于var/let來說,只聲明而未初始化,此時變量存儲的信息是“空”的,也就是undefined;但是對于const來說,只聲明而不進行初始化是不允許的,會拋出Missing initializer in const declaration的錯誤,因為const定義的是常量,一旦定義便不可更改。
聲明提升(hoisting)
var命令聲明的變量會發生”聲明提升“現象,即變量可以在聲明之前使用,值為undefined;
console.log(aa);// undefined var aa = "string"; console.log(aa);// string
function聲明的函數也會發生”聲明提升“現象,函數在聲明之前可以使用,值為指向該函數的指針;但是如果是在支持ES6的環境中,ES6允許在塊級作用域內聲明函數,此時在塊級作用域中聲明的函數,會提升到所在的塊級作用域的頭部,值為整個函數塊,同時還會提升到塊級作用域外,但是值為undefined。(環境導致塊級作用域內聲明函數的行為差異非常大,所以應該避免在塊級作用域內聲明函數。如果確實需要,也應該寫成函數表達式,而不是函數聲明語句)
console.log(fn);// ? fn(){} function fn(){} console.log(fn);// ? fn(){} //支持es6的環境中 console.log(fb);// undefined if(true){ console.log(fb); // ? fb(){} function fb(){} } console.log(fb);// ? fb(){} console.log(fc);// undefined if(false){ console.log(fc); // 未執行 function fc(){} } console.log(fc);// undefined fc() //Uncaught TypeError: fc is not a function
函數和變量都會聲明提升,此時若函數名和變量名同名,函數名的優先級要高;但是正式執行代碼時,同名函數會覆蓋只聲明卻未賦值的變量,但是它不能覆蓋聲明且賦值的變量(原因分析可見另一篇文章JavaScript基礎系列---執行環境與作用域鏈)
console.log(bb);// ? bb(){} var bb; function bb(){} console.log(bb);// ? bb(){} console.log(cc);// ? cc(){} var cc = "string"; function cc(){} console.log(c)c;// string
局部變量/函數(函數作用域function塊里面的變量/函數)也會聲明提升,可以先使用后聲明,不影響外部同名變量/函數
let和const命令改變了語法行為,它們所聲明的變量一定要在聲明后使用,否則報錯。由于let和const命令在當前塊級作用域內不可重復聲明所以當有同名函數時,會直接報錯Identifier xx has already been declared
參考資料《JavaScript高級程序設計第三版》
ECMAScript 6 入門
MDN變量
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/95063.html
摘要:所以,有另一種說法認為閉包是由函數和與其相關的引用環境組合而成的實體。所以本文中將以維基百科中的定義為準即在計算機科學中,閉包,又稱詞法閉包或函數閉包,是引用了自由變量的函數。 閉包(closure)是JavaScript中一個神秘的概念,許多人都對它難以理解,我也一直處于似懂非懂的狀態,前幾天深入了解了一下執行環境以及作用域鏈,可戳查看詳情,而閉包與作用域及作用域鏈的關系密不可分,所...
摘要:內存泄露內存泄露概念在計算機科學中,內存泄漏指由于疏忽或錯誤造成程序未能釋放已經不再使用的內存。判斷內存泄漏,以字段為準。 本文是 重溫基礎 系列文章的第二十二篇。 今日感受:優化學習方法。 系列目錄: 【復習資料】ES6/ES7/ES8/ES9資料整理(個人整理) 【重溫基礎】1-14篇 【重溫基礎】15.JS對象介紹 【重溫基礎】16.JSON對象介紹 【重溫基礎】1...
摘要:調用堆棧是存放原始數據類型的地方除了函數調用之外。上一節中聲明變量后調用堆棧的粗略表示如下。解釋改變的正確方法是更改內存地址。在聲明時,將在調用堆棧上分配內存地址,該值是在堆上分配的內存地址。 這是專門探索 JavaScript 及其所構建的組件的系列文章的第 21 篇。 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 如果你錯過了前面的章節,可以在這里找到它們:...
摘要:前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點分為新聞熱點開發教程工程實踐深度閱讀開源項目巔峰人生等欄目。背后的故事本文是對于年之間世界發生的大事件的詳細介紹,闡述了從提出到角力到流產的前世今生。 前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點;分為新聞熱點、開發教程、工程實踐、深度閱讀、開源項目、巔峰人生等欄目。歡迎...
摘要:它對數組和對象使用按值傳遞,但這是在的共享傳參或拷貝的引用中使用的按值傳參。例如在這里,變量和值在執行期間存儲在堆棧中。返回值這是可選的,函數可以返回值,也可以不返回值。變量被推入堆棧,從而在執行時成為的副本。 這是專門探索 JavaScript 及其所構建的組件的系列文章的第 22 篇。 想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你! 如果你錯過了前面的章節,可...
閱讀 2915·2021-11-25 09:43
閱讀 2342·2021-11-24 09:39
閱讀 2724·2021-09-23 11:51
閱讀 1416·2021-09-07 10:11
閱讀 1461·2019-08-27 10:52
閱讀 1948·2019-08-26 12:13
閱讀 3369·2019-08-26 11:57
閱讀 1406·2019-08-26 11:31