JavaScript 基本觀念紀錄
執行時期 - 在準備資料
開發時期 - 開始實作
JavaScript 物件
可以指派給一個 變數
並會在執行時期擁有 型別
- 物件(Object)
- 這裡的物件代表存在於記憶體中的資料
- 僅存於執行時期
- 變數(Variable)
- 記憶體指標特性(可以指向任何資料)
- 只能在開發時期宣告 var , let , const
- 在執行時期只會用來儲存物件的記憶體位置
- 型別(Type)
- 僅存於執行時期,並用來標示物件的種類(類型)
- 不同型別之間可能會有不同的屬性與方法
1 | var a |
JavaScript 都是物件
- number
- string
- boolean
- null - (此變數可能曾經有值,可能沒有值) 現在沒有值
- undefind - 此變數還沒有給值,所以不知道是什麼
- symbol
- array
- object
- regexp
變數
建立方式
先建立物件
在建立型別
,型別
用來標示物件的種類
1 | var a = “5” |
a = 變數 , 5 = 物件 , “” = (字串)型別
1 | a.name = “jimmy" |
a = 變數物件 , name = 屬性 , jimmy = 物件 , “” = (字串)型別
屬性
1 | a.name = {} |
- 可以被刪除
- 內含記憶體指標特性(可以指向任何資料)
- 任何一個 JavaScript 只有屬性
變數(也可能是屬性)
1 | let a = {} |
- 絕對無法刪除(除非去 prototye 刪除父連結)
- 內含記憶體指標特性(可以指向任何資料)
- 沒有型別
- 在記憶體裡指向別人
- var , let , const 進行宣告
宣告變數 | var | let | const |
---|---|---|---|
作用域 | Function scope | Block scope | Block scope |
注意事項 | 盡量不用 var,會汙染 window(全域變數) 造成一堆變數在 window | var 宣告過的變數,不能再使用 let 宣告一次 | 宣告一個唯讀的變數 (變數無法再指向其他物件) |
hosting | undefined | is not defined | is not defined |
作用域
- var ( funcotion socpe )
1 | function myFunction () { |
- let ( block scope )
1 | function myFunction () { |
注意事項
- var
- 污染全域(window)
1 | var a = 1 |
- let
- 不會污染全域(window)
1 | var a = 1 |
hosting
- 當 function 與變數/常數同名稱而提升時,function 的優先程度高於變數/常數
1 | a() |
- var
- undefind
1 | console.log (myVar) // undefined |
- let
- TDZ
- 程式碼中某個部份變數的參考動作還不能執行,這是因為該變數尚未被初始化
- TDZ
1 | console.log (myVar) // ReferenceError: myVar is not defined |
- const
- TDZ
1 | console.log (myVar) // ReferenceError: myVar is not defined |
變數指派差異
- var
- 一般變數下
- 可以重新修改變數值
- 可以重新宣告變數
- 在 object 和 array 下
- 可以重新修改 object 和 array 的變數值
- 可以重新宣告 object 和 array 變數
- 一般變數下
1 | var myVar = 2 ; |
- let
- 一般變數下
- 可以重新修改變數值
- 不能重新宣告變數
- 在 object 和 array 下
- 可以重新修改 object 和 array 的變數值
- 不能重新宣告 object 和 array 變數
- 一般變數下
1 | let myVar = 2 ; |
- const
- 一般變數下
- 不能重新修改變數值
- 不能重新宣告變數
- 在 object 和 array 下
- 可以重新修改 object 和 array 的變數值
- 不能重新宣告 object 和 array 變數
- 一般變數下
1 | const myVar = 2 ; |
型別
型別分類
- 原始型別(Primitive Type) - 不允許自由擴增
屬性
- 但卻有屬性 & 方法可以使用,因為有原始型別包裹物件 (primititve type wrapper type) & 父元素的關係
1 | 'abc'.charAt === String.prototype.charAt // true |
運算元 | 型別 |
---|---|
Number (數值) | number |
String (字串) | string |
Boolean (布林) | boolean |
Null (空值) | object |
Undefind (未定義) | undefind |
Symbol (符號) | function |
- 物件型別(Object Type) - 可以自由擴增屬性
運算元 | 型別 |
---|---|
Array (陣列) | object |
Object (物件) | object |
型別判斷
typeof
- null 是基本型別之一,得到 object,而非 null
- function 是物件的子型別,但 typeof function() {} 是得到 function ,而非 object
- NaN 表示是無效的數字,但依舊還是數字,因此結果就是 number,而非「不是數字」(not a number)
- NaN 與任何數字運算都會得到 NaN,並且 NaN 不大於、不小於也不等於任何數字,包含 NaN 它自己
1 | typeof 'Hello World!' // 'string' |
instanceof
- 檢查物件是否為指定的建構子所建立的實體
- 用來測試一個 object 在原型鏈中是否存在一個構造函數的 prototype 屬性
- 涉及的構造函數
- 基礎類型:string、number、boolean、undefined、null、symbol
- 複雜類型:array,object
- 其他類型:function、regExp、date
- 語法
- [對象] instanceof [構造函數], 回傳 boloon 值
- 注意左側必須是對象(object),如果不是,直接返回 false
1 | let obj = new Object() |
基礎類型
- 檢測的一定要是對象(object)
1 | // 第一個不是 object,是基本類型,返回 false |
複雜類型
- 直接生成構造函數,所以不會像基本類型一樣兩種情況
1 | let arr = [ ] |
其他類型
- 除了 function,都一樣是 object
1 | // 這裡要注意,function A() {}相當於 let A; A = function(){} |
型別參數傳遞
- 參數傳遞
Call by reference | Call by value |
---|---|
Object | String |
Array | Number |
Function | Boolean |
RegExp | Null |
Date | Undefined |
Math | Symbol |
Call by value
- 佔用不同記憶體位置
1 | let age = 100; |
Call by reference
- 使用相同記憶體位置
- 記憶體「路徑位置」會被複製
1 | let superTeam = ['Otree', 'Penguin', 'Frog', 'Jim']; |
Call by Sharing (共享參考)
- 變數值被呼叫時,會直接把該變數所在的記憶體位置做為參考,傳遞給呼叫它的對象
- 但當對象被
賦予新值
時,對象會被指定一個新的記憶體位置
,值也跟著變了
1 | let superTeam = ['Otree', 'Penguin', 'Frog', 'Jim']; |
- 為何會產生不同傳遞方式的錯覺?
- 在 JavaScript 中所有的 Call by value 型別皆為不可變動的(Immutable)
- 永遠只能藉由賦予新值的方式將值傳遞給新的變數
物件
物件取屬性值
- “ . “
- […]
- 可取出 number 屬性的屬性值
1 | // 建立物件 |
物件複製
- 物件複製的內容,儲存在不同的記憶區塊,讓彼此不會影響 ?
- Object.assign(target, …sources)
- Shallow Copy
- 只能處理深度只有一層的物件,沒辦法做到真正的 Deep Copy
- target - 目標物件
- sources - 來源目標
- Shallow Copy
1 | const person = { |
- JSON.parse(JSON.stringify(obj))
- Deep Copy
- JSON.stringify 序列化(轉成字串)
- JSON.parse 物件化(轉成物件)
- function、regExp、undefind 過不去
- Deep Copy
1 | const person = { |
- jQuery - Deep Copy & Shallow Copy
- extend 可以複製物件,可以將加入參數使用深度複製 (deep copy)
- merge object 順序會影響到結果
- shallow copy
- jQuery.extend( target [, object1 ] [, objectN ] )
- deep copy
- jQuery.extend( [(deep)true or false], target, object1 [, objectN ] )
1 | var object1 = { |
- 函式庫 lodash - Deep Copy & Shallow Copy
- shallow copy
- _.clone()
- deep copy
- _.cloneDeep()
- shallow copy
1 | var objects = [{ 'a': 1 }, { 'b': 2 }]; |