一、介紹
這是紅寶書(JavaScript高級程序設計 3版)的讀書筆記第四篇,是紅寶書第四章內容(主要是變量和作用域問題),當然其中還有我個人的理解。紅寶書這本書可以說是難啃的,要看完不容易,挺厚的,要看懂更不容易,要熟練js更是難,中間需要不斷的積累與重溫。因此不是讀一兩遍就能把這書吃透,需要多讀,可謂溫故而知新,可以為師矣。
同系列:
第一篇:JavaScript--我發現,原來你是這樣的JS(一)(初識)
第二篇:JavaScript--我發現,原來你是這樣的JS(二)(基礎概念--軀殼篇,不妨從中文角度看js)
第三篇:JavaScript--我發現,原來你是這樣的JS(三)(基礎概念--靈魂篇)
二、變量
1 .變量介紹:
javascript 中的變量是松散型的,既不用去指定改變量的數據類型值,聲明變量時直接使用一個操作符var就行。
//聲明變量
var str = 'string';
var num = 123;
//當不用var時,則為全局變量但不推薦這樣操作
i = 123;
2.變量的兩種值:基本類型和引用類型的值:
js的變量有兩種不同的數據類型的值:基本類型的值和引用類型的值。
- 基本類型上一篇提到的五種基本類型:null ,undefined,boolean,string,number
- 引用類型一般是:對象,函數,數組等,都是object類型
//基本類型的值
var num = 123;
var boo = false;
//引用類型的值
var obj = new Object();
var arr = new Array();
var arr2 = {};
3.基本類型的值和引用類型的值的區別
區別一:動態的屬性
動態的屬性怎么理解:就是可以動態的增加,刪除,改變屬性和方法
- 對於基本類型的值,不能夠進行這些操作
//基本類型的值
var str = '123';
//添加屬性
str.age = 123;
console.log(str.age); //undefined,說明該值沒被聲明,所以基本類型屬性沒有動態的屬性
- 對於引用類型的值,能夠進行這些操作,例子沒毛病
//引用類型的值
var person = new Object();
//添加屬性name
person.name = 'ry-yuan';
//添加方法sayHi
person.sayHi = function(){
console.log('hi');
}
console.log(person.name); //輸出ry-yuan
person.sayHi(); //輸出hi
區別二:復制變量值不同
- 對於基本類型變量值之間的復制,會創建一個新值給另一變量,彼此不會相互影響,例子:
var n1 = 100;
//n1復制給n2
var n2 = n1;
console.log(n2); //100
//對n2操作自增
n2++;
console.log(n1); //100,n1不會受n2影響
console.log(n2); //101
- 對於引用類型之間復制,則不會創建新值,而是 指向同一個對象
//引用變量值
var o1 = new Object();
//復制o1給o2
var o2 = o1;
//為o1添加屬性
o1.name = 'ry-yuan';
//o2也會有這個屬性值
console.log(o2.name); //'ry-yuan'
為什么引用類型會指向同一個對象?因為o1中存着的值只是一個對象的引用地址,所以o1復制到o2時就把地址復制給o2,兩者的地址相同,所以指向同一個對象。
區別三:傳遞參數
這里的傳遞參數是對函數傳遞參數。函數參數的按值傳遞的。傳遞參數的兩者的區別和上面復制的一樣。
- 對於基本數據類型的值,對函數傳遞參數,是將值復制給函數內部的參數,復制另一份獨立的值,所以兩者不影響彼此。
var n = 123;
function add(num){
num ++;
console.log(num);
}
//將n傳給函數add
add(n); //124
console.log(n); //123,n不會被影響
- 對於引用數據類型的值,對函數傳遞參數,是將對象在的引用地址值復制給函數內部參數(局部變量),所以操作的是同一個對象。
//引用類型
var p = new Object();
function addName(obj){
obj.name = 'ry-yuan';
}
console.log(p.name); //undefined,對象沒有name屬性
//將p傳進函數
addName(p);
console.log(p.name); //ry-yuan,對象有了name屬性
區別四:檢測類型
- 對於基本數據類型,我們使用
typeof
來確認變量是什么基本數據類型
var num = 666;
var str = "hello ry";
var boo = false;
var und = undefined;
var n = null;
console.log(typeof num); //number
console.log(typeof str); //string
console.log(typeof boo); //boolean
console.log(typeof und); //undefined
console.log(typeof n); //object,特別的null返回的是object
- 對於引用類型的值,我們使用
instanceof
操作符,判斷它是什么類型的對象。不用typeof的原因是typeof檢測引用類型都會返回object,這不是我們想要的,我們想知道它是什么類型的object
//這里想知道arr是不是數組類型,如果是返回true,不是返回false
console.log(arr instanceof Array);
//這里想知道arr是不是正則類型,如果是返回true,不是返回false
console.log(arr instanceof RegExp);
- 特別的:用
instanceof
去判斷基本類型值都會返回false,因為基本類型數據都不是object,就更不用判斷是什么類型的object了。
三、作用域
作用域:是變量與函數的可訪問范圍,即作用域控制着變量與函數的可見性和生命周期。在JavaScript中,變量的作用域有全局作用域和局部作用域兩種。
1.全局執行環境:
最外圍的一個執行環境,在web瀏覽器中,全局執行環境被認為是window對象,因此所有的全局變量和函數都是作為window對象的屬性和方法創建的。
2.局部執行環境:
局部執行環境是指在函數內部,函數被創建,就會有一個函數作用域,在函數內定義的變量和方法,函數外面不能訪問,但函數內可以訪問外面的變量和方法。
//聲明一個全局變量,當前最外圍是全局作用域
var g = 1;
//聲明函數fn1
function fn1(){
//局部作用域
//聲明一個變量
var i = 10;
//可以訪問g
console.log(g); //1
//再聲明一個函數fn2
function fn2(){
//局部作用域
var j = 100;
//可以訪問g和i
console.log(g); //1
console.log(i); //100
}
//fn1不能訪問到fn2里面的變量和方法
console.log(j); //報錯,j沒被定義
}
//全局作用域中不能訪問i,j
console.log(i); //報錯,i沒有被定義
console.log(j); //報錯,j沒有被定義
上圖:
全局作用域中只能訪問紅顏色中有的變量和函數,有g和fn1
局部作用域fn1中能訪問紅色+藍色中的變量和函數,有g,i,fn1,fn2
局部作用域fn2中能訪問整個所有的變量和函數g,i,j,fn1,fn2
綜上越里面的作用域訪問的就越多。有種不能滲透到內部,只能向外拓展的感覺。
3.沒有塊級作用域
什么是塊級作用域:用大括號括起來的區域{ coding.... }
js中沒有塊級作用域,所以有一下這種情況:
for(var i =0 ; i<10 ; i++){
console.log(i);
}
console.log(i); //10 ,這里會有結果,i沒有被銷毀
查詢標記符:
查詢標記符怎么操作?
來個例子:
var a = 1;
function getNum(){
return a ;
}
console.log(getNum()); //1
我們來分析一下變量a 的查找過程:
1.首先在getNum函數作用域中找,發現沒有a變量
2.於是向外拓展,到了全局作用域,發現,哎,有a,var了個a,沒錯就是你了。然后獲得這個a。
再來一個例子:
var b = 1;
function get(){
var b = 2;
return b;
}
console.log(get()); //2
這次又是怎么操作:
1.在執行函數get時,我們聲明了一個b變量,return時需要用到b,這時我們在局部作用域中找,哎,有了,有個b變量,就是你了,然后就返回了。不用再到外面找了。
4、垃圾回收問題:
1.什么是js的垃圾回收機制?
答:javascript中垃圾收集機制是自動回收的,不用人工操作,這讓我們更專注於編輯代碼上。 回收垃圾機制是定時執行的,具有周期性。
2.什么時候會有垃圾?
答:在作用域中當整個作用域中的代碼執行完后,作用域中的變量和方法都會沒用,此時就是被當做垃圾了。比如局部作用域,一個函數執行完,里面的變量就可以被銷毀,其占用內存被釋放。
3.垃圾回收方式?
答:常用的是標記清除:這樣操作:一個變量-->進入環境(被標記,有此標記為不能被清除)-->執行-->離開環境(被標記,這個標記告訴機制能被清除)-->回收機制一段周期后,變量被清除。
4.為什么還要管理內存?
答:分配給web瀏覽器的內存比桌面的應用的內存少,這是出於安全考慮,為了防止運行js的網頁耗盡系統內存導致系統崩潰。所以,開發者發現一旦數據不再用時,就將其值設為null來釋放其引用(解除引用),這做法適用於全局變量和全局對象屬性。
五、說說
博文好久沒更新啦,墮落了,啊啊啊啊,努力努力,積極向上。最近挺多事。不能擋我學習,通通閃開。
本文出自博客園:http://www.cnblogs.com/Ry-yuan/
作者:Ry(淵源遠願)
歡迎訪問我的個人首頁:我的首頁
歡迎訪問我的github:https://github.com/Ry-yuan/demoFiles
歡迎轉載,轉載請標明出處,保留該字段。