TypeScript里面的有些概念,是C++开发人员无法直接理解的。
在TFJS里面,每一个object都通过大括号初始化,然后用作WeakMap的关键字:
export type DataId = object;
const dataId = {}; //DataId类型
初始化之后,这个dataId就不再更改了。原因是,虽然初始化的过程都是一样的大括号,但是,对应的却是不同的对象。
TFJS的具体例子如下:
const dataId = {};
譬如下面的例子:
write(values: backend_util.BackendValues, shape: number[], dtype: DataType):
DataId {
const dataId = {};
this.tensorMap.set(dataId, {
dtype,
values,
bufferInfo: {byteSize, usage: DEFAULT_GPUBUFFER_USAGE}
});
return dataId;
}
下面的代码,比较了使用大括号初始化的两个object,他们是不同的:
var wm1 = new Map()
const o1 = {};
const o2 = {};
wm1.set(o1, 37);
wm1.set(o2, 'abcde');
console.log("wm1.get(o1)="+wm1.get(o1));
console.log("wm1.get(o2)="+wm1.get(o2));
if (o1 ===o2)
console.log("o1 === o2");
console.log(o1.toString());
console.log(o2.toString());
console.log(JSON.stringify(o1));
console.log(JSON.stringify(o2));
wm1.set(o1, 'abcde');
console.log("wm1.get(o1)="+wm1.get(o1));
console.log("wm1.get(o2)="+wm1.get(o2));
write(values: backend_util.BackendValues, shape: number[], dtype: DataType):
DataId {
const dataId = {};
// dataId.oid = Math.floor((Math.random() * 10000) + 1);
// console.log("write oid="+dataId.oid);
const objectId = Math.floor((Math.random() * 10000) + 1);
Object.defineProperty(dataId, 'first', {
value: objectId,
writable: false,
enumerable: true,
configurable: true
});
this.tensorMap.set(dataId, {
dtype,
values,
bufferInfo: {byteSize, usage: DEFAULT_GPUBUFFER_USAGE}
});
console.log('write JSON.stringify(dataId)=' + JSON.stringify(dataId));
return dataId;
}
async read(dataId: object): Promise {
if (!this.tensorMap.has(dataId)) {
throw new Error(`Tensor ${dataId} was not registered!`);
}
const info = this.tensorMap.get(dataId);
const data = await this.getBufferData(info);
const dataAsTypedArray =
webgpu_util.ArrayBufferToTypedArray(data as ArrayBuffer, info.dtype);
console.log('read JSON.stringify(dataId)=' + JSON.stringify(dataId));
this.convertAndCacheOnCPU(dataId, dataAsTypedArray);
console.log('read end JSON.stringify(dataId)=' + JSON.stringify(dataId));
return dataAsTypedArray;
}
构造函数里面的成员变量,如果添加了private或者public,那么,这些成员变量都可以通过this来访问。否则,这些变量仅仅构造函数内部可见。外部不可见。
class Greeter {
constructor(private message: string) {
}
greet() {
return this.message;
}
}
let greeter = new Greeter("world");
console.log(greeter.greet());
class Greeter {
constructor(private message: string, public message2: string) {
}
greet() {
return this.message+","+this.message2;
}
}
let greeter = new Greeter("world","public");
console.log(greeter.greet());
Map和WeakMap有两点区别。
一,WeakMap的关键字必须是object类型(不能是数字等原语类型,primitives)。Map则没有这个限制。
/*From: https://javascript.info/weakmap-weakset#weakmap*/
let weakMap = new WeakMap();
let obj = {};
weakMap.set(obj, "ok"); // works fine (object key)
// can't use a string as the key
weakMap.set("test", "Whoops"); // Error, because "test" is not an object
二,GC对两者的key的处理方法不一样。如果是Map,那么GC的时候,key所代表的对象是不会被回收的。但是WeakMap里面,如果key所代表的对象仅仅存在于WeakMap里面,那么是可能被回收的。
WeakMap的使用场景:它不影响对象的生命周期。它提供了一个旁观者视角。
参考文献:
https://www.mattzeunert.com/2017/01/31/weak-maps.html
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
https://javascript.info/weakmap-weakset