Tomas:
每一個利用 Symbol 產生的值都是獨特的,他的屬性無法用 for in Object.getOwnPropertyNames 取得。
(可用 getOwnPropertySymbols)
補充 Map , Set, WeakMap, WeakSet
Lai:
建構器形式的值建立動作(new String(“abc”))的結果是一個包裹了基型值的物件包裹器,而非只是建立基型值本身。
如果想要取用物件包裹器中底層的基本型別值,可以使用valueOf()方法。
基本型別值沒有特性或方法,會需要包裹基型值的物件包裹器,JS會自動封裝,以利存取。
日安:
顯示封裝器的方法:Object.prototype.toString(..)方法。
建立一個包在 false 值的物件包裹器,但物件本質還是 truthly。
取出其底層的基本型別值,可以使用 valueof() 方法。
mango:
String(), Number(), Boolean()這三個natives,不用new就會自動封裝
在new Array()時要避免有empty
Object()這個native本身就是物件,再用new的方式太多餘
Object.prototype.toString() ≠ xxx.toString()
用 XXX.constructor.name
也可以看型別
基本型別建構式 與 Object 型別建構式 用途不一樣
不要修改 prototype 的本意
kai:
稀疏陣列 ≠ 陣列裡面放 undefined (empty ≠ undefinde)
JS 會自動封裝
不要去修改原生原型的東西
Andy:
這些對象包裝器服務於一個非常重要的目的。基本類型值沒有屬性或方法,所以為了訪問.length或.toString()你需要這個值的對象包裝器。值得慶幸的是,JS將會自動地封箱(也就是包裝)基本類型值來滿足這樣的訪問。
Array構造器有一種特殊形式,如果它僅僅被傳入一個number參數,與將這個值作為數組的內容不同,它會被認為是用來“預定數組大小”(嗯,某種意義上)用的長度。
Henry
可以透過 Object.prototype.toString.call 得知[[Class]] 屬性
JS 預設會自動封裝,所以 primitive 也可以取用 methods
(忘了)
Jason
Object.prototype.toString().call()“來抓到[[class]]`是哪個型別
JS會自動封裝,所以在宣告變數的時候,不需再宣告 data type
Array的不要亂建構(new),會大事不好
Tony:
知道 Native 是否能夠作為建構器
成為建構器有哪些注意事項
純值 使用方法時,用建構器與 Native 的差異。
Jimmy
Natives是由JS提供包覆基本型別值用的物件包裹器
JS會自動封裝基本型別值
共筆
最常用的幾個 natives:
String()
Number()
Boolean()
Array()
Object()
Function()
RegExp()
Date()
Error()
Symbol()
這些 natives 實際上是內建函式,確實可以被當作一個原生建構器,但建構出來的東西可能與你想像的不同:
var a = new String(“abc”);
typeof a; //Object
a instanceof String //true
Object.prototype.toString.call(a); // [object String]
建構式形式所創建的結果,是一個包裹了基型值的物件包裹器。typeof 顯示出這些物件,並非他們自己的特殊型別,他們是 object 的子型別。
重點是 new String(“abc”) 建立了一個字串包裹器物件,包裹了abc,而非基型值本身。
Internal [[Class]]
typeof 為”object”的那些值,會額外標示有一個內部的[[Class]]特性。這個特性無法直接被取用,但可借取Object.prototype.toString(..)方法,來間接揭露此特性。
Object.prototype.toString.call(null);
// “[Object Null]”
Object.prototype.toString.call(undefined);
// “[Object Undefined]”
多數情況,內部的 Class 值,會對應到該值關聯的原生建構式中,但也有例外狀況,像是建構式 Null() 和 Undefined() 都不存在,但儘管如此,顯露的還是 “Null” 和 “Undefined”。
相對於其他簡單基型值,像是 string、number、boolean,實際上會有其他行為的涉入。
封裝後的包裹器
物件包裹器具有非常重要的用途,基本型別值沒有特性或方法,所以要存取length或toString,會需要包裹基型值的物件包裹器。
在跑 for 迴圈的時候,最好的方法可能是讓值有物件的形式,但實際上程式會執行得更慢,最好是讓自動封裝的動作隱含的發生,換句話說就是永遠不要使用原生建構式,而使用字面形式的基本型別值。
物件包裹器的陷阱
假設真的要使用原生建構式,有幾個陷阱:
var a = new Boolean(false);
if(!a) {
console.log(“Oops!”); //永遠都不會執行
}
建立一個包在 false 值的物件包裹器,但物件本質還是 truthly。
如果要手動封裝一個 Object,可以使用 Object(…)函式(不帶new)。
解封裝
想要取出其底層的基本型別值,可以使用valueof()方法。
var myName = new String(‘Jason’);
var weight = new Number(96);
var isHenry = new Boolean(true);
myName.valueOf();//”Jason”
weight.valueOf();//96
isHenry.valueOf();//true
typeof myName.valueOf(); //”string”
typeof weight.valueOf(); //”number”
typeof isHenry.valueOf(); //”boolean”
解封裝的動作也可能隱含的發生,會造成強制轉型:
var myName = new String(‘Jason’);
var sumEmpty = myName + “”;
//sumEmpty擁有解封後的基本型別值 “Jason”
// 「myName +」 就是 「myName.valueOf() +」
typeof myName;//”object”
typeof sumEmpty;//”string”
作為建構式的 Natives
最偏好的方式是使用字面表示來建立基本型別值,這些字面形式的值會與建構式形式所創建的物件相同。
Array
Array 建構式,如果只有一個 number 引數被傳入,那麼建構式不會把該值當作陣列的內容,而是將他當成一個長度來預先設定陣列的大小。但實際上並沒有「預先設定陣列大小」這種事存在,取而代之建立出來的是一個空陣列,不過該陣列length被設定為所指定的那個數值。插槽中沒有明確的值,意味著陣列中的插槽會是undefined。
Object()、Function()、RegExp()
幾乎沒有什麼情況會用到 new Object()。
你得動態定義一個函式的參數或其函式主體的時候才會用得到 Function()。
應該優先選用字面值形式定義正規表示式,JS 引擎會在程式碼執行前預先編譯,並快取。
Date(..)、Error(..)
Date() 和 Error()兩者沒有字面表示式的形式可用。
要建立一個日期物件,除了增加參數,還可以使用Date().getTime()方法。
使用 Error 物件的主要狀況,通常是用於執行堆疊情境,錯誤物件的實體通常會有一個message特性,通常最好是做錯誤物件上呼叫toString方法,已取得格式化方便閱讀的錯誤訊息。
Symbol
ES6中加入一個額外的基本型別值型別,叫做「Symbol」。主要是為了建構器特殊的內建行為設計。
Symbols 主要用於私有或特殊屬性。
const test1 = Symbol(“hello”);
const test2 = Symbol(“hello”);
console.log(test1 === test2); //false
//Tomas
Symbol 取值
相同 key 值
// Tomas 的範例
const obj = {};
const a = Symbol(“a”);
const b = Symbol(“b”); //key 值相同
const c = Symbol(“b”); //key 值相同
obj[a] = ‘Hello’;
obj[b] = ‘World’;
obj[c] = ‘yo!’;
const objectSymbols = Object.getOwnPropertySymbols(obj);
console.log(obj[objectSymbols[1]]); // “World”
console.log(obj[objectSymbols[2]]); // “yo!”
// Turtle 的範例
var info = {
name:’Jason’,
[Symbol(‘description’)]:’CSS很強’,
};
var otherInfo = {
[Symbol(‘description’)]:’很愛性騷擾同事’
};
var Person = Object.assign({},info,otherInfo);
//{name: “Jason”,
//Symbol(description): “CSS很強”,
//Symbol(description): “很愛性騷擾同事”}
es6-feature 上面的範例
// Tomas 的範例
//
Symbol(“foo”) !== Symbol(“foo”)
const foo = Symbol()
const bar = Symbol()
typeof foo === “symbol”
typeof bar === “symbol”
let obj = {}
obj[foo] = “foo”
obj[bar] = “bar”
JSON.stringify(obj) // {}
Object.keys(obj) // []
Object.getOwnPropertyNames(obj) // []
Object.getOwnPropertySymbols(obj) // [ foo, bar ]
原生的原型
每個原生建構式都有自己的prototype,而這些方法不會直接修改字串,修改動作會從現有的值建立出一個新的值。
做為預設值的原型
Function.prototype是空的函式,RegExp.prototype是空的正規表達式,Array.prototype是空的陣列,這使得他們適合拿來做預設值,可以給尚未擁有適當型別值的變數。
副作用:當設預設值重新創建,會耗費記憶體和 CPU。
const test1 = Symbol(“hello”);
const test2 = Symbol(“hello”);
console.log(test1 === test2); //false
Array.from({length: 10}).map((_,index) => index);
//創建某個長度的陣列
var range = Array.from({length: 10})
for (x of range) {
console.log(‘here’)
}
range es-6
var configObject = {}
Array.prototype.push.call(configObject, “new element”)
configObject // {0: “new element”, length: 1}
Array.from(configObject) // [“new element”]
Object 的 Subtype 的原生建構式使用
转载请注明:XAMPP中文组官网 » YDKJS 第三次讀書會