JavaScript
Object.create()
The Object.create() static method creates a new object, using an existing object as the prototype of the newly created object.
可以用它来取得父class的prototype来赋值给子class的prototype来实现继承:
function Person(fName, lName) {
this.firstName = fName;
this.lastName = lName;
}
Person.prototype.getFullName = function () {
return this.firstName + ' ' + this.lastName;
}
function Employee(fName, lName, eId) {
// 调用父class的constructor.
Person.call(this, fName, lName);
this.empId = eId;
}
// 这里的prototype就和Person的prototype完全相等。
Employee.prototype = Object.create(Person.prototype);
Employee.prototype.constructor = Employee;
Symbol
将Symbol作为key赋值object需要使用中括号:
const obj = {prop1: 123, [Symble('test2')]: 456}
用for...in 来循环一个iterable对象或者Object.keys()、JSON.stringify()的时候不会包含里面的Symbol key, 这是为了向前兼容,因为es5的时候并不认识Symbol。
for-inignores Symbol-keyed properties
const obj = {
[Symbol("x")]: "foo"
};
for (const name in obj) {
console.log(`name = ${String(name)}`); // never runs
}
但是依然可以使用Reflect.ownKeys()来获得所有的key,包含string和Sybol:
function tryToAddPrivate(o) {
o[Symbol('Pseudo Private')] = 42;
}
const obj = { prop: 'hello' };
tryToAddPrivate(obj);
console.log(Reflect.ownKeys(obj)); // [ 'prop', Symbol(Pseudo Private) ]
console.log(obj[Reflect.ownKeys(obj)[1]]); // 42
Symbol.for()
会在全局注册范围内搜索给定的key的Symbol, 如果没找到则生成它:
console.log(Symbol.for('bar') === Symbol.for('bar'));
// Expected output: true
console.log(Symbol('bar') === Symbol('bar'));
// Expected output: false
const symbol1 = Symbol.for('foo');
console.log(symbol1.toString());
// Expected output: "Symbol(foo)"
Symbol.iterator
The Symbol.iterator static data property represents the well-known symbol @@iterator. The iterable protocol looks up this symbol for the method that returns the iterator for an object. In order for an object to be iterable, it must have an @@iterator key.
无论什么样的object,只要实现了[Symbol.iterator]属性就实现了iterable protocol , 可以被for...in循环和进行解构。
const iterable1 = {};
iterable1[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
console.log([...iterable1]);
// Expected output: Array [1, 2, 3]
Symbol的好处
防止object的属性名冲突
const library1property = Symbol('lib1');
function lib1tag(obj) {
obj[library1property] = 42;
}
const library2property = Symbol('lib2');
function lib2tag(obj) {
obj[library2property] = 369;
}
虽然用library1property和library2property赋值成random string也能防止冲突,但是Symbol的方案有个好处就是可以隐藏Symbol的key,让循环或者JSON.stringify()时对外不可见,这就保证了如果使用的lib方法中添加了lib中的属性时,这个属性是private的。
其实也可以用如下方法来让string的key来模仿Symbol:
const obj = {};
obj[Symbol()] = 1;
Object.defineProperty(obj, 'foo', {
enumberable: false,
value: 2
});
console.log(Object.keys(obj)); // []
console.log(Reflect.ownKeys(obj)); // [ 'foo', Symbol() ]
console.log(JSON.stringify(obj)); // {}
比如下方如果user是import自另外一个module的,然后我们想在user上加上自己的属性但是又不想影响module原本的功能:
let user = { // belongs to another code
name: "John"
};
let id = Symbol("id");
user[id] = 1;
alert( user[id] ); // we can access the data using the symbol as the key