詞法結構
字符集
使用Unicode編寫
- ES3 Unicode2.1+
- ES5 Unicode3+
區分大小寫
註釋
// 註釋
/*
註釋
*/
標識符和保留字
必須以字母、下劃線、美元符開始,後續字符可以是字母、數字、下劃線、美元符,即數字不能作爲首字符
保留字
可選的分號
Javascript只有在缺少了分號就無法正確解析代碼的時候纔會填補分號。
一般,一條語句以(、[、/、+、-開始,它極有可能和前一條語句一起解析。return、break、continue除外
類型、值和變量
數據類型:在編程語言中、能夠表示並操作的值的類型
變量:一個值的符號名稱,可以通過該名稱獲得值的引用。
數據類型
一般分類
- 原始類型:數字、字符串、布爾值、null、undefined
- 對象(屬性的鍵值對集合)類型:數組、普通對象、函數類、日期類、正則類、錯誤類
其他分類
- 可以擁有方法的類型和不能擁有方法的類型
- 可變類型(數字、布爾值、null、undifined、字符串)和不可變類型(對象、數組)
數字
javascript採用IEEE 754標準定義的64位浮點格式表示數字,最大值±1.7976931348623157E+308,最小值±5E-324
能夠表示的整數範圍爲-2E+53~2E+53。實際操作(如數組索引)是基於32位整數。
注意: 小數精度問題,如0.1+0.2 != 0.3 ,需要轉成整數計算,計算完成再轉回小數。產生原因是Number採用的時IEEE 754 64位雙精度浮點數編碼,浮點數無法精確表示其值範圍內的所有數值,導致十進制轉換成二進制時有舍入模式,產生了誤差
格式
- 整形直接量
- 浮點直接量
算術運算
上溢出(正負無窮)使用±Infinity表示,下溢出(無限接近於0)則返回0(±0)。
NaN和任何值都不相等,包括自身。
二進制浮點數和四捨五入錯誤
在javascript使用實數時,常常只是真實值的一個近似表示。
let x=0.3-0.2
let y=0.2-0.1
x==y // false
x==0.1 // false
y==0.1 // true
// 由於舍入誤差,0.3和0.2之間的近似差值實際上不等於0.2和0.1之間的近似差值
文本
字符串是一組由16位值組成的不可變的有序序列。字符串長度是其所含的16位值的個數。
轉義字符
布爾值
true或者false
可轉換爲false的值:undefined、null、0、-0、NaN、''。
null和undifined
- typeof null爲object,含義爲非對象
- undifined 未定義值
全局對象
全局屬性、全局函數、構造函數、全局對象
包裝對象
存取字符串、數字或布爾值的屬性時創建的臨時對象叫包裝對象。
不可變的原始值和可變的對象引用
可變類型(數字、布爾值、null、undifined、字符串)和不可變類型(對象/引用類型、數組)。
類型轉換
轉換和相等性
顯式類型轉換
變量聲明
如果給一個未聲明的變量賦值(不可配置),實際上會給全局對象創建一個同名屬性(可配置),不建議這樣用。
創建一個全局變量實際上是給全局對象創建了一個屬性。
變量作用域
一個變量的作用域是程序源代碼中定義這個變量的區域。
- 函數作用域、塊級作用域。
- 聲明提前
類型檢測
- typeof 用於基礎類型和函數判斷
- instanceof用於對象類型判斷
-
Object.prototype.toString.apply([])==='[object Array]'
null、undifined失效
表達式和運算符
表達式
表達式分爲簡單表達式(常量、變量名)和複雜表達式(由簡單表達式組成)。
原始表達:
表達式的最小單位,
- 直接量(包括:數字、字符串、布爾,不包括數組、對象)
- 關鍵字
- 變量
由簡單表達式可以組合成複合表達式
複雜表達式
- 對象和數組的初始化表達式
- 函數定義表達式
- 屬性訪問表達式
- 調用表達式
- 對象創建表達式
運算符
說明:
- 下圖按照優先級高到低排序,水平線分割的具有不同的優先級
- A列表示運算符結核性,L(左到右) R(右至左)
- N列表示操作數的個數
- 類型列表示期望的操作數類型以及運算符的結果類型
分類
按照操作數個數分:一元(+1)、二元(1+2)、三元(?:)
左值
表達式只能出現在賦值運算符的左側。變量、對象屬性、數組元素均是左值。
算術表達式
一元算術運算符
作用於一個單獨的操作數,併產生一個新值,具有很高的優先級,且均爲右結合。
-
+
:轉換爲數字或者NaN,並返回轉換後的值 -
-
:和+
一樣,但是會改變結果的符號。 -
++
和--
:運算符在操作數前,操作數±1並返回計算後的值;運算符在操作數之後,操作數±1,並返回計算前的值。 -
,
逗號運算符,從左到右一次執行,返回最右邊的值
關係表達式
- in
- instanceof
邏輯表達式
賦值表達式
其他運算符
- ?:
- typeof
- delete
- viod
- ,逗號運算符,從左到右計算,最後返回最右邊的值
語句
聲明語句
- 變量var let
- 函數function
條件語句
switch
switch(expression){
statements
}
// expression中計算是使用===
循環
do/while
do{
statements
} while(expression)
// 至少執行一次
for/in
// 將對象中的所有屬性複製到一個數組中
var o = {x:1,y:2,z:3};
var a = [], i = 0;
for(a[i++] in o) /* empty */;
跳轉
標籤語句
mainloop: while(token I= null) {
// 忽略這裏的代碼...
continue mainloop; //跳轉到下一次循環
// 忽略這裏的代碼...
}
//從標籤名開始,以便在報錯時退出程序
compute_sum: if (matrix) {
for(var x = o; x < matrix.length; x++) {
var row= matrix[x];
if (!row) break compute_sum;
for(var y = o; y < row.length; y++) {
var cell= row[y];
if (isNaN(cell)) break compute_sum; sum+= cell;
}
}
success= true;
}
// break語句跳轉至此II如果在success== false的條件下到達這裏, 說明我們給出的矩陣中有錯誤//否則將矩陣中所有的元素進行求和
其他語句類型
width
// 臨時擴展作用域鏈
with(document.form[0]){
name.value=""
}
try/catch
try{
xxxx
}catch(e){
xxx
}finally{
xxx
}
對象
創建對象
- 對象直接量創建的對象原型爲Object.prototype
- 通過new創建的對象原型爲使用的原構造函數的prototype
- Object.create()創建的對象原型爲第一個參數,也可設置爲null
屬性的查詢和設置
屬性訪問錯誤
查詢屬性和原型有關,設置與原型無關(如果設置屬性爲繼承屬性,且具有setter方法時,將執行setter,而不是給當前對象創建新的屬性)
下列情況給對象O設置屬性P會失敗
- O中屬性P是隻讀的(defineProperty()方法中有例外)
- O中的P是繼承的,且是隻讀的
- O中不存在屬性P,O中沒有使用setter方法繼承屬性P,並且O的可擴展性()是false
檢測屬性
- in:
x in o
- hasOwnProperty:
O.hasOwnProperty(x)
- propertyIsEnumerable:
o.propertyIsEnumerable(x)
,hasOwnProperty的增強版,自身屬性且可枚舉 - o.x!==undefined x的值爲undefined則需要使用in
屬性的特性
- 值 value
- 可寫性 writable
- 可枚舉性 enumerable
- 可配置性 configurable
獲取自身屬性的特性
Object.getOwnPropertyDescriptor({x:1},'x')
// 返回{value:1,writable:true,enumerable:true,configurable:true}
設置屬性的特性
// 單個
Object.definePeoperty(o,'x',{
value:1, // 值
writable:true, // 可讀
enumerable:true, // 可遍歷
configurable:true // 可改變配置
})
// 批量
Object.definePeoperties(o,{
x:{
value:1,
writable:true,
enumerable:true,
configurable:true
},
y:{
value:1,
writable:true,
enumerable:true,
configurable:true
}
})
對象的三個屬性
原型
- 查詢原型
Object.getPrototypeOf()
- 檢測是否包含某個原型
p.isPrototypeOf(o)
,p是否是o的原型
類屬性
可以通過toString獲取對象的類屬性
function classof(o){
if(o===null) return 'Null';
if(o===undefined) return 'Undefined';
return Object.prototype.toString.call(o).slice(8,-1);
}
classof({}) // => 'Object'
可擴展性
- 查詢可擴展性
Object.isExtensible(o)
- 轉換成不可擴展
Object.preventExtensions(o)
- 封閉:轉換爲不可擴展且所有屬性不可配置
Object.seal()
,可使用Object.isSealed()
來檢測是否封閉 - 凍結:轉換爲不可擴展且所有屬性不可配置、所有屬性只讀
Object.freeze()
,可以使用Object.isFrozen()
來檢測是否凍結
序列化
JSON.stringify(),JSON.parse()具可接受第二個參數,標識需要序列化或還原的屬性列表
對象方法
- toJSON()
- valueOf()將對象轉換成原始值
數組
創建數組
- 數組直接量
[]
,該語法有可選的結尾逗號,故[,,]
只有兩個元素而非三個 new Array()
new Array() // 創建一個空數組
new Array(10) // 創建一個長度爲10的數組
new Array(5,4,3) // 創建一個已包含數組元素數組
稀疏數組
稀疏數組並不是項的值爲undefined,而是不存在
// 三種方式創建
// 1
new Array(5)
// 2
a=[]
a[1000]=0
// 3
delete
數組方法
*標識爲變異方法
- join
- reverse *
- sort *
- concat
- slice
- splice *,返回刪除元素組成的數組
- push/unshift *,返回數組新的長度
- pop/shift * 返回刪除元素的值
- toString/toLocalString 無方括號,逗號分隔
- forEach
- map
- filter,可以使用來壓縮稀疏數組
- every 所有元素調用判定函數,均返回true才返回true
- some 所有元素調用判定函數,有一個返回true就返回true
- reduce/reduceRight
// 求和、第二個參數爲temp的初始值,不傳默認使用數組中的第一個元素
arr.reduce((temp,value,index,arr)=>temp+value, 0)
- indexOf/lastIndexOf
數組類型
判斷使用Array.isArray(arr)
判斷是否是數組
函數
構造函數:用於初始化一個新創建的對象的函數
函數定義
兩種定義方式及區別:
- 函數聲明語句,可以在定義前使用(函數聲明前置);不能出現在循環、條件、try/catch/finally、with中
- 函數定義表達式,不能在定義前使用(變量聲明前置);可以出現在任何地方
- 函數構造器
函數調用
四種調用方式:
- 作爲函數:this在非嚴格模式爲全局對象,嚴格模式爲undefined
- 作爲方法:this爲方法所屬對象
- 作爲構造函數:this爲新構造的對象
- call()或者apply()間接調用:this爲指定的對象
函數的實參與形參
不定實參函數:可以接收任意個數的實參,通過arguments(類數組對象)接收參數
作爲命名空間的函數
立即調用函數
(function(){
}())
閉包
詞法作用域,函數內變量作用域是在函數定義時創建的,而不是在調用時創建,且在函數執行時,定義時的作用域鏈依然有效。
函數對象可以通過作用域鏈相互關聯起來,函數體內部的變量都可以保存咋子函數作用域內,這種特性叫閉包。
函數屬性、方法和構造函數
length 形參個數
arguments 參數對象(類數組對象)
prototype 指向原型對象
apply、bind、call
- apply 將函數作爲指定對象thisObj的方法來調用,傳遞給它的是指定的參數數組args
function.apply(thisObj,args)
- call 將函數作爲指定對象thisObj的方法來調用,傳遞給它的是指定的參數,如果thisObj爲null,則爲全局對象
function.call(thisObj,arg1,arg2,...)
- bing 返回一個新函數,通過可選的指定參數,作爲指定對象obj的方法調用該方法,傳遞給該函數的參數由兩部分組成,一部分是傳遞給bind()的args數組指定的參數,剩下的是傳給這個新函數的所有值。
傳入bind()的實參都是放在傳入原始函數的實參列表開始的位置。
function.call(obj,arg1,arg2,...)
// 示例:
let g=f.bind(obj,1,2)
g(3)
// 等價於
f.call(obj,1,2,3)
toString
Function()構造函數,最後一個實參爲函數體
函數式編程
高階函數
操作函數的函數,接收一個或者多個函數作爲參數,並返回一個函數。
不完全函數
傳入bind()的實參都是放在傳入原始函數的實參列表開始的位置。
作用域
分類
- 全局
- 函數,塊級(ES6+)
- eval
作用域鏈
變量對象
用於存儲執行上下文中的:
- 變量
- 函數聲明
- 函數參數
1.變量初始化階段
2.代碼執行階段
類和模塊
特性:封裝、繼承、多態、抽象
類名使用大駝峯命名。ES6直接使用class,下面是ES6之前的。
構造函數和類的標識
原型對象是類的唯一標識:當切僅當兩個對象繼承自同一個原型對象時,它們才屬於同一個類的實例。
construsctor
構造函數是類的公共標識,construsctor屬性爲對象提供了類。
let 0= new F()
0.construsctor===F // => true
javascript中的java式的類繼承
創建一個類分爲三步:
- 定義一個構造函數,並設置初始化新對象的實例屬性
- 給構造函數的prototype對象定義實例方法
- 給構造函數定義類字段和類屬性
類的擴充
javascript中基於原型的繼承機制是動態的,如果創建對象之後原型的屬性發生變化,也會影響到繼承這個原型的所有實例,即我們可以通過給原型對象添加方法來擴充Javascript類。
類和類型
instanceof:
obj instanceof c
obj.isPrototypeOf(f)
constructor:
x.constructor===Number
構造函數的名稱
Object.prototype.toString.call(o)
注意:
- 前兩種方法在多個執行上下文無效
- 這三種方法都有一個問題,就是不是所有對象都有constructor屬性
鴨式辯型
Javascript中的面向對象技術
標準轉換方法
- toString()
- toLocaleString()
- valueOf()
- toJSON()
方法借用
Object.prototype.xxx=xxx
子類
- 方法鏈
- 構造函數鏈
正則表達式的匹配模式
定義
- 直接量
- 構造器
內容
直接量字符
字符類
重複
非貪婪重複在匹配字符後加一個?即可。
選擇、分組、引用
指定匹配位置
修飾符
String方法
- search
- replace
- match
- split
RegExp對象
屬性:
- source
- global
- ignoreCase
- multiline
- lastIndex
方法:
- exec
- test
javascript的子集和擴展
迭代
迭代器
Iterator(),返回迭代器
for(let [k,v] in Iterator({a:1,b:2}))
console.log(k+"="+v) // a=1,b=2
特性:
- 只針對自有屬性進行遍歷,忽略繼承屬性
- 第二個參數傳true,則只遍歷屬性名。忽略值
數組推導*
[expression for (varuable in object) if(conditon)]
函數簡寫
表達式閉包:如果函數只計算一個表達式並返回它的值,關鍵字return和花括號可以省略
let succ=function(x)x+1
多catch從句
E4X
jsx語法