Chapter 1 - Javascript物件
* Function接(),會產生一個執行物件(function return後如無參考,則會被GC),並會傳回這個function的return value
* Function冠用new(此時稱此function為建構函式),會產生一個執行物件,並傳回這個物件
* function(){return {ID: 1}}() 跟 new function(){this.ID = 1} 都會傳回一個物件,差別是前者不會有prototype繼承
- 是嘛?在Chrome裡都有耶?
* 尚未明白為何的地方:
* 尚未明白為何的地方:
- Function裏面有return,執行物件可以接()執行!!
- Function沒有return,就只是執行物件
* 九大原生物件
- Number, String, Boolean, Array, Object, Function, RegExp, Date, Error
* 原生物件標準需由new運算子產生,但可用字面值(Literal)來產生
- var n = 1
- var s = "string"
- var b = true
- var a = [1,2,3]
- var o = {ID: 1}
- var f = function(){}
- var r = /.*/
* 值分為原始值(Simple Value)與複合值(Complex Value)
- 原始值
- 複製:完全複製
- 比較:比較其值
- 屬性:沒這檔事
- 複合值(就像指標啦)
- 複製:僅複製參考
- 比較:比較參考
- 屬性:可以加入屬性
* 原始值包括6類:
- null
- undefined
- "string"(雙引號字串)
- 123(單純的數字)
- true
- false
* 當使用Literal產生Number, String, Boolean時,得到的是原始值(Simple value)
* Number, String, Boolean
- 需特別注意當產生方式不同時(原始值/複合值),行為有所不同
* 物件的Constructor是"指向"他的建構函數
- 所以判斷物件類型的方法之一是比對Constructor是否為某個函數
Chapter 2 - 應用物件與屬性
* Complex Value的屬性可以是大部分的js value
* 可以亂裝(就JSON)
* 屬性可以透過obj.prop或obj['prop']存取
- 括號法功能較強:
- 屬性名稱可以由字串組合
- 屬性名稱可為數字或保留字, ex: obj['123'], obj['object']
* 從物件中移除屬性用delete
* 尋找屬性:原型鍊(Prototype Chain) (就是繼承鍊!)
0. 目前物件為obj
1. 先找obj下面
2. 再找obj.constructor.prototype
3. 再找obj.constructor.constructor.prototype
4. 都沒有,回傳undefined
* hasOwnProperty() v.s. in 運算元 (注意屬性在此是以名稱(字串啦)來詢問)
- hasOwnProperty()
- 若為true,表示屬性不是從原型鍊來的。
- in
- 若為true,表示該物件的原型鍊找的到該屬性。
* 尋訪屬性,可使用 for-in loop
- 會列出包含原型鍊內的所有屬性。可用 hasOwnProperty()檢查
- 只會列出可列舉的(enumerable)的屬性,可用propertyIsEnumerable()檢查
* Host物件
- 非javascript標準內的物件,ex. 瀏覽器提供的,
- 其中必有一個Head物件,也就是環境物件, ex. window
Chapter 3 - Object()
* new Object()可填initial value,物件會成為該value所屬原生物件的物件
* 繼承鍊的源頭Object.prototype (注意Object不是實體)
Chapter 4 - Function()
* 函數:一個陳述式的執行範圍
* 在函數名稱後加上()代表執行此函數
* new Function(arg1,...., argn),可吃n個參數,前面是建構出的Function的參數,最後一個是函數內容的字串
- var func = new Function('a', 'b', 'return a+b')
- var func = function(a, b) {return a+b}
* 上面那種作法會用到eval()造成運算浪費
* 沒有指定return的函式會回傳undefined
* arguments
- 所以函數可以不給定指定的參數
- 也可以給沒指定的參數
- arguments.callee指向函數本身
- arguments.length是函數被呼叫時得到的參數量 (1.4之後Deprecated,只能arguments.callee.length取得函數指定的參數數量)
* this
- 這個函數屬於那個物件
- 若是Global,則指向環境物件
* length
- var func = function(a, b , c){} 則 func.length === 3
* 函數建立4種方式
- var funcConstructor = new Function('a', 'b', 'return a+b');
- function funcStatement(a, b) { return a+b; }
- var funcExpression = function(a, b) { return a + b; }
- var funcNamedFunction = function funcNamedFunction(a, b) { return a + b; }
* 函式使用4種方式
- 當函式執行,就是加上()來執行
- 當方法執行,一樣是()
- 當建構式使用,配合new
- apply()或call(),用途是改變所屬物件(也就是this)
* function aaa(){} 沒有aaa就叫匿名函式
* 可以無限巢狀
* 函式可以當作參數傳入函式,也可以當作return value被回傳
* Javascript執行前會解譯程式,所以可以在函式宣告之前使用函式
* 函式可以遞迴呼叫
Chapter 5 - Head/Global 物件
* Head物件包含所有的物件,透過範圍鍊所有地方都可以呼叫Head物件的成員,故就像全域屬性一樣
* 參考Head物件
- 直接參考其名稱(ex. 瀏覽器是window)
- 在全域範圍內使用this
* 在全域範圍中進行宣告,用var不用var有些微差異
- 用var 是屬性
- 不用 是變數
* 因為Head是範圍鏈的最後一站,所以他可以是隱式的。通常使用Head物件的成員不會明確參考Head物件
- window.alert()
- alert() <-- br="" clear="none" usually="">-->
Chapter 6 - this關鍵字
* this參考到函式所在的物件
- 例外:使用new、apply()、call()
* 巢狀函式內,this
- ES3:this會迷失,而指到Head
- ES5:會正常指到應該的物件
* 常用that來避免this迷失
* apply()跟call()可以指定this的值
* 當使用new呼叫函式時,this會參考到等等要被new出來的物件
- 如果不用new呼叫,那就會在函式所屬物件產生新的屬性。(通常就是window了XD)
* 在prototype中的函式參考到this,this會指向實際的instance,而不是prototype
Chapter 7 - 範圍與Closure
* Javascript的Scope有:
- 全域範圍
- 函式範圍
- eval()範圍
* Javascript沒有區塊範圍( {} )
* 以var宣告的變數會是在當前範圍內宣告,沒有用var宣告的會被宣告在全域範圍
* 若同樣的變數名稱在不同的範圍內,會傳回最近的那個值
* 範圍鍊是在"定義"函式時決定的,而非在呼叫過程中決定
- 這就叫作語彙範圍(Lexical Scoping)
Chapter 8 - 函式原型屬性
* 預設的prototype是一個Object()物件
* Firefox2+/Safari/Chrome可以這樣參考prototype
- obj.__proto__
* EMCA標準參考方式
- obj.constructor.prototype
* Prototype鍊會傳回第一個找到的屬性,所以會有屏蔽效應
* 若是修改A物件預設的prototype,那用A物件new出來的物件其constructor不會是A(),而是Object()
- 要避免必須在a的prototype內加入constructor為a
* prototype鍊是動態參考的,所以當你修改了prototype的內容,所有的Instances都會參考到最新的內容
* 但若直經更換整個prototype,現有的Instances還是會參考到舊的prototype
* 一旦建立Instances了,就不該更換prototype,避免物件有不一致的行為
* prototype繼承鍊的原始用意是要摹仿傳統物件導向的繼承機制
Chapter 9 - Array()
* Array(1,2,3)會建立一個長度為3且初始值分別為1,2,3的陣列
但Array(5)則會建立一個長度為5的空陣列
* 透過更改length屬性,會讓Array實質的長大或變小
* 陣列裏面可以存放陣列,而有多維陣列的行為
* 向後尋訪陣列
var count = 0
while (count < arr.length){
count++;
}
* 向前尋訪陣列
var count = arr.length
while(count--) {
}
Chapter 10 - String()
* a = "abc"; typeof a是String
a = new String("abc"); typeof a是Object (!!!!)
Chapter 11 - Number()
* 第1點跟String一樣,請使用Literal產生Number避免typeof變成Object
* 可以使用hex或oct表達法
- var a = 0xff //a = 255
- var b = 012 //a = 10
Chapter 12 - Boolean()
* 第1點,一樣, String()/Number()/Boolean()都有這個問題
* var a = new Boolean(false); console.log( a ? "true" : "false"); 會log true。WTF
* 0, -0, null, false, NaN, undefined, ""會被轉換成false,其他都是true
Chapter 13 - 使用原始字串、數字、布林值
* 原始值在存取時,會變轉換成物件,提供該物件的屬性。完成屬性的存取後,該物件就會被捨棄,又變回原始值
* 如果要直接存取數字原始值的屬性,必須在被轉換成物件之間對數字賦值(evaluate),例如 1..toString() (<- br="" clear="none">->
(這超不懂的,WTF)
* 避免使用new建構式產生原始值,避免typeof變成Object()
Chapter 14 - null
* null用來表示某個屬性存在,但沒有值
* 檢驗null,請用 ===
- typeof 會是 Object()
- ==無法區分null與undefined
Chapter 15 - undefined
* 用途一:表示一個變數尚未被賦值
* 用途二:表示一個屬性不存在(包括在繼承鍊裡也找不到)
* 不該自行把某變數賦值為undefined,因為此時你宣告了變數了,他不是不存在,只是空值,應該要給null
Chapter 16 - Math
* Math是特別的內建物件,無法用他產生instance,因為他沒有建構式
* Math內大寫開頭的常數屬性,無法改變他們的值