第三章、型別、值和變數
JavaScript的資料型別分為兩類:原始型別(primitive type)和物件型別(object type).
原始型別包括數字、字串和布林值
兩個特殊的原始值null(空)和undefined(未定義)
物件是屬性(property)的集合,每個屬性都是由"名/值對"(值可以是原始值)
普通的JavaScript物件是"命名值"的無序集合——陣列(arry),表示帶編號的值的有序集合
另一種特殊物件函式
數字
JavaScript不區分整數值和浮點數值
1.整型直接量
2.浮點型直接量
3.JavaScript中的算術運算
加、減、乘、除、求餘
複雜運算子
4.二進位制浮點數和四捨五入錯誤
5.日期和時間
JavaScript語言核心包括Date()建構函式
var then=new Date(2017,6,2); //2017年7月2日
var later=new Date(2017,6,2,17,10,30); //同一天,當地時間5:10:30pm
var now=new Date(); //當前日期和時間
var elapsed=now - then; //日期減法,計算時間間隔的毫秒數
later.getFullYear(); //=>2017
later.getMonth(); //=>6:從0開始計數的月份
later.getDate(); //=>2:從1開始計數的天數
later.getDay(); //=>5:得到星期幾
later.getHours(); //=>當地時間:15
later.getUTCHours(); // 使用UTC表示小時的時間,基於時區複製程式碼
文字
字串(string)是一組由16位值組成的不可變的有序序列
JavaScript通過字串型別來表示文字
1.字串直接量
在JavaScript程式中的字串直接量,是由單引號或雙引號括起來的字元序列
2.轉義字元
3.字串的使用
"+ " 字串的拼接
var s="hello world" //定義一個字串
s.charAt(0) //=>"h":第一個字元
s.chartAt(s.length-1) //=>"d":最後一個字元
s.substing(1,4) //=>"ell":第2~4個字元
s.slice(-3) //=>"rld":最後三個字元
s.indexOf("l") //=>2:字元l首次出現的位置
s.lastIndexOf("l") //=>10:字元l最後一次出現的位置
s.indexOf("l",3) //=>3:在位置3及之後首次出現字元l的位置
s.split(", ") //=>["hello","world"]分割成子串
s.replace("h","H") //=>"Hello,world":全文字元替換
s.toUpperCase() //=>"HELLO,WORLD"複製程式碼
4.模式匹配
JavaScript定義了RegExp()建構函式,用來建立表示文字匹配模式的物件。
正規表示式,JavaScript採用Perl中的正規表示式語法
布林值
布林值指代真或假、開或關、是或否。這個型別只有兩個值,保留字true和false
任意JavaScript的值都可以轉化為布林值。下面這些值會被轉換為false:
undefined
null
0
-0
NaN
"" //空字串複製程式碼
運算子:&& || !
null 和 undefined
null 空值,對null執行typeof預算,結果返回字串"object"。它可以表示數字、字串和物件是"無值"的
undefinde更深層次的"空值",對undefined執行typeof預算,結果返回字串"undefined"。它是變數的一種取值,表明變數沒有初始化
全域性物件(global object)
- 全域性屬性,比如undefined,Infinity和NaN
- 全域性函式,比如isNaN(),parseInt()和eval()
- 建構函式,比如Date(),RegExp(),String(),Object()和Array()
- 全域性物件,比如Math和JSON
包裝物件
JavaScript物件是一種複合值:它是屬性或已命名值的集合。
字串eg:
var str='hello world';
str.substring(str.indexOf(" "),str.length) //=>" world"複製程式碼
只要引用了字串str的屬性,JavaScript就會將字串值通過呼叫new String(str)的方式轉換為物件,這個物件繼承了字串的方法,並被用來處理屬性的引用。一旦屬性引用結束,這個新建立的物件就會銷燬
null和undefined沒有包裝物件,訪問它們的屬性會造成一個型別錯誤
不可變的原始值和可變的物件引用
1.JavaScript的原始值(undefined,null,布林值,數字和字串)與物件(包括陣列和函式)有著根本區別。
2.原始值是不可更改的;原始值的比較是值的比較;
3.物件的比較並非值的比較;兩個單獨的物件永不相等
型別轉換
JavaScript將根據需要自行轉換型別
10 + "objects" //=>"10 objects"數字10轉換為字串
"7" * "4" //=>28:兩個字串均轉換為數字
var n = 1 - "x"; //=>NaN:字串"x"無法轉換為數字
n + "objects"; //=>"NaN objects":NaN轉換為字串"NaN"複製程式碼
2.true轉換為1,false轉換為0
3.原始值通過呼叫String(),Number()或Boolean()建構函式,轉換為它們各自的包裝物件
4.轉換和相等性
(1)."=="相等運算子也隨相等的含義靈活多變,如下這些比較結果均是true:
null == undefined; //這兩值被認為相等
"0" == 0 //在比較之前字串轉換成數字
0 == false //在比較之前布林值轉換為數字
"0" == false //在比較之前字串和布林值都轉換為數字複製程式碼
5.顯式型別轉換
(1).最簡單的方法是使用Boolean(),String(),Number()或Object()函式
Number("3"); //=>3
String(false); //=>"false" 或使用 false.toString()
Boolean([]); //=>true
Object(3); //=>new Number(3)複製程式碼
除了null或undefined之外的任何值都具有toString方法
6.隱式型別轉換
x + "" //等價於String(x)
+x //等價於Number(x).也可以寫成x-0
!!x //等價於Boolean(x).注意是雙歎號複製程式碼
7.物件轉換為原始值
所有的物件繼承了兩個轉換方法。toString()和valueOf()
1.toString() 物件到字串
[1,2,3].toString(); //=>"1,2,3" 將每個陣列元素轉換為字串
(function(x) {f(x);}).toString(); //=>"function(x){\n f(x); \n}" 這個函式的實現定義的表示方式
/\d+/g.toString(); //=>"/\\d+/g" 將RegExp物件轉換為表示正規表示式直接量的字元
new Date(2017,6,9).toString(); //=>"Sun Jul 09 2017 00:00:00 GMT+0800 (中國標準時間)"
({x:1,y:2}).toString(); //=>"[object Object]"複製程式碼
2.valueOf() 物件到數字
eg1:
var d = new Date(2017,6,9);
d.valueOf(); //=>1499529600000複製程式碼
eg2:
var d = new Date(); //建立一個日期物件
typeof(d + 1); //=>"string":"+"將日期轉換為字串
typeof(d - 1); //=>"number":"-"使用物件到數字的轉換
d == d.toString() //=>true:隱式的和顯示的字串轉換
now > (now - 1) //=>true:">"將日期轉換為數字複製程式碼
變數宣告
1.在JavaScript中,使用一個變數之前應當先宣告
2.如果未在var宣告語句中給變數指定初始值,那麼雖然宣告瞭這個變數,但在給它存入一個值之前,它的初始值就是undefined
3.在for和for-in迴圈中同樣可以使用var語句
4.重複的宣告和遺漏的宣告
變數作用域
1.一個變數的作用域(scope)是程式原始碼中定義這個變數的區域
2.全域性變數擁有全域性作用域
3.區域性變數,函式內宣告的變數只在函式體內有定義
4.在函式體內,區域性變數的優先順序高於同名的全域性變數
var scope = "global"; //宣告一個全域性變數
function checkscope(){
var scope = "local"; //宣告一個同名的區域性變數
return scope; //返回區域性變數的值,而不是全域性變數的值
}
checkscope();複製程式碼
5.函式定義是可以巢狀的
var scope = "global scope"; //全域性變數
function checkscope(){
var scope = "local scope"; //區域性變數
function nested(){
var scope = "nested scope"; //巢狀作用域內的區域性變數
return scope; //返回當前作用域內的值
}
return nested();
}
checkscope();複製程式碼
6.函式作用域和宣告提前
(1).同一個作用域內
function test(o){
var i = 0; // i 在整個函式體內均是有定義的
if(typeof o == "object"){
var j = 0; // j在函式體內是有定義的,不僅僅是在這個程式碼段內
for(var k = 0;k < 10;k++){ // k 在函式體內是有定義的,不僅僅是在迴圈內
console.log(k); //輸出數字0~9
}
}
} 複製程式碼
(2).JavaScript的函式作用域是指在函式內宣告的所有變數在函式體內始終是可見的。
宣告提前(hoisting)
var scope = "global";
function f(){
cocnsole.log(scope); //輸出"undefined",而不是"global"
var scope = "local"; //變數在這裡賦初始值,但變數本身在函式體內任何地方均是有定義的
console.log(scope); //輸出"local"
}
f();
真實轉換:
function f(){
var scope; //在函式頂部宣告瞭區域性變數
console.log(scope); //變數存在,但其值是"undefined"
scope = "local"; //這裡將其初始化並賦值
console.log(scope); //這裡它具有了我們所期望的值
}複製程式碼
將變數宣告放在函式體頂部
7.作為屬性的變數
var truevar = 1; //宣告瞭一個不可刪除的全域性變數
fakevar = 2; //建立全域性物件的一個可刪除的屬性
this.fakevar2 = 3; //同上
delete truevar; //=>false:變數並沒有被刪除
delete fakevar; //=>true:變數被刪除
delete this.fakevar2; //=>true:變數被刪除複製程式碼
JavaScript全域性變數是全域性物件的屬性。
8.作用域鏈
(1).在JavaScript的最頂層程式碼中(也就是不包含在任何函式定義內的程式碼),作用域鏈由一個全域性物件組成。
(2).在不包含巢狀的函式體內,作用域鏈上有兩個物件,第一個是定義函式引數和區域性變數的物件,第二個是全域性物件。
(3).在一個巢狀的函式體內,作用域鏈上至少有三個物件。