FE 讀書會(二):Data Types
Data Types
ECMAScript 標準定義了七種資料型別:
除了物件以外的所有值,都是原始定義的值(值意味著不能被改變)。我們引用這些類型的值為
primitive values(原始值)
。
- Boolean
- Number
- String
- Null
- Undefined
- Symbol(於 ECMAScript 6 新定義)
- Object
Boolean, Number, String, …
定義是….你認真的???
Undefined vs Null
空(null)就是空值,代表的是沒有值的意思。
In JavaScript null is not a “reference to a non-existing object” or a “null pointer” like in some other languages.
It’s just a special value which has the sense of “nothing”, “empty” or “value unknown”.
未定義(undefined)即是尚未被定義(not been assigned)類型,或也有可能是根本不存在,完全不知道是什麼。
A variable that has not been assigned a value is of type undefined.
A method or statement also returns undefined if the variable that is being evaluated does not have an assigned value.
A function returns undefined if a value was not returned.
** undefined is not a reserved word
適用情境
雖然JavaScript並沒有明確規範這兩個資料類型的用途,但對JavaScript程式設計師而言,應儘量: - 使用空值(null)來進行運算後判斷或當特殊情況回傳值
- 未定義(undefined)就留給JavaScript系統用,常用typeof運算符的判斷方式。
Symbol
ES6新增的Data type.
初始化
Symbol(); // symbol
Symbol('foo'); // description: foo
console.log(Symbol()); // prints "Symbol()" to the console
assert(typeof Symbol() === 'symbol')
new Symbol(); // TypeError: Symbol is not a constructor
特色
- Symbols 絕對不會與 Object 的 string keys衝突
- Symbols 不能用既有的Reflection取得, 且不是private的
- Symbols 不能與其他primitives運算
- Symbols 不總是唯一值
Symbols 絕對不會與 Object 的 string keys衝突
var myObj = {};
var fooSym = Symbol('foo');
var otherSym = Symbol('bar');
myObj['foo'] = 'bar';
myObj[fooSym] = 'baz';
myObj[otherSym] = 'bing';
assert(myObj.foo === 'bar');
assert(myObj[fooSym] === 'baz');
assert(myObj[otherSym] === 'bing');
Symbols 不能用既有的Reflection取得, 且不是private的
Symbols 不會顯示在使用 for in、 for of 或者 Object.getOwnPropertyNames的Object上,在Object中獲取Symbol的唯一方法是Object.getOwnPropertySymbols
var fooSym = Symbol('foo');
var myObj = {};
myObj['foo'] = 'bar';
myObj[fooSym] = 'baz';
Object.keys(myObj); // -> [ 'foo' ]
Object.getOwnPropertyNames(myObj); // -> [ 'foo' ]
Object.getOwnPropertySymbols(myObj); // -> [ Symbol(foo) ]
assert(Object.getOwnPropertySymbols(myObj)[0] === fooSym);
Symbols 不能與其他primitives運算
如果用(+Symbol(), “+Symbol(), Symbol() + ‘foo’) 會出錯…
Symbols 不總是唯一值
完全唯一的狀況
建立一個 symbol,它會在 JavaScript引擎建立一個全新的值。如果没有reference Symbol,你就不能使用它。這代表兩個symbols永遠不會等於相同的值, 即使description一樣.
除非出現下列狀況
除非是使用Symbol.for(), 這表示在global Symbol registry建立一個Symbols。此 registry 是跨域的,代表同一個iframe 或 service worker 的symbol會跟目前frame的symbol會完全一樣
assert.notEqual(Symbol('foo'), Symbol('foo'));
assert.equal(Symbol.for('foo'), Symbol.for('foo'));
// Not unique:
var myObj = {};
var fooSym = Symbol.for('foo');
var otherSym = Symbol.for('foo');
myObj[fooSym] = 'baz';
myObj[otherSym] = 'bing';
assert(fooSym === otherSym);
assert(myObj[fooSym] === 'bing');
assert(myObj[otherSym] === 'bing');
// Cross-Realm
iframe = document.createElement('iframe');
iframe.src = String(window.location);
document.body.appendChild(iframe);
assert(iframe.contentWindow.Symbol.for('foo') === Symbol.for('foo')); // true!
好像還是不太懂… 看看有些適合的使用情境
可以用在String 或Integer的作為唯一值使用的地方
比如logger.levels.DEBUG, logger.levels.INFO, logger.levels.WARN 等等。
過去使用要用String(logger.levels.DEBUG ===‘debug’)或Integer(logger.levels.DEBUG === 10)。這兩個有可能不是唯一值, 會有衝突風險. 但Symbols 的特性是!所以logger.levels 很容易改成这样:
log.levels = {
DEBUG: Symbol('debug'),
INFO: Symbol('info'),
WARN: Symbol('warn'),
};
log(log.levels.DEBUG, 'debug message');
log(log.levels.INFO, 'info message');
** In some programming languages, Symbols are called atoms
. You can also compare them to named enumerations (enum)
in C.
A place to put metadata values in an Object
You could also use them to store custom metadata properties that are secondary to the actual Object.
var size = Symbol('size');
class Collection {
constructor() {
this[size] = 0;
}
add(item) {
this[this[size]] = item;
this[size]++;
}
static sizeOf(instance) {
return instance[size];
}
}
var x = new Collection();
assert(Collection.sizeOf(x) === 0);
x.add('foo');
assert(Collection.sizeOf(x) === 1);
assert.deepEqual(Object.keys(x), ['0']);
assert.deepEqual(Object.getOwnPropertyNames(x), ['0']);
assert.deepEqual(Object.getOwnPropertySymbols(x), [size]);
Reference
What data types are supported in Javascript?
Object
請準時參加下周課程
Author Leefu Chen
LastMod 2018-05-07