使用和理解JavaScript地图



JavaScriptMap对象上的MDN文档提供了有用的信息,但似乎忽略了一些重要的点。也许它们对大多数人来说是显而易见的,但我不清楚为什么它会这样工作,我希望能澄清。

键(如果不是字符串(似乎是对包括函数对象在内的对象的引用。而且,除了函数对象之外,对象的值似乎也是对对象的引用。因此,在下面的代码中,mapF.get(updateFunc).b = 25更新映射中保持的对象,而不是mapF.get()仅返回对象的副本。

但是,当值是函数对象时,这似乎不适用于这种情况,而是似乎复制了函数,因此在更新函数funcInMap后,mapF.get('funcInMap')(4)返回8而不是12;并且因此看起来持有CCD_ 7的原始定义的副本。

我是在犯错误,还是这是它的工作方式和应该期望的工作方式?非常感谢。

var funcInMap = function (x) {
return x * 2;
};
function updateFunc() {
funcInMap = function (x) { return x * 3; };
}
var mapF = new Map();
mapF.set(updateFunc, {a: 5, b: 10});
mapF.set('funcInMap',funcInMap);
console.log("b pre map update: " + mapF.get(updateFunc).b); // 10
mapF.get(updateFunc).b = 25;
console.log("b post map update: " + mapF.get(updateFunc).b); // 25
console.log(mapF.get(updateFunc));
console.log("funcInMap pre update : " + mapF.get('funcInMap')(4)); // 8
updateFunc();
console.log("funcInMap post update : " + funcInMap(4)); // 12
console.log("mapF funcInMap post update : " + mapF.get('funcInMap')(4)); // 8

收到答案后添加。

function updateFunc() { }

var mapF = new Map(),
obj = {a: 5, b: 10};
mapF.set(updateFunc, obj);

console.log("Original obj: " + Object.values(mapF.get(updateFunc))); 
// Return 5, 10
obj = {a: 105, b: 110};

console.log("Updated obj: " + Object.values(mapF.get(updateFunc))); 
// Return 5, 10

/*
I would've been stupid to expect the second group to return
105, 110; but that is what I was expecting when the objects
were functions.
*/

在将我的一些项目代码更改为使用映射而不是常规对象之后,我突然想到,在将mapkey设置为具有valueobject时,我又有点愚蠢了。也许在某些情况下,这是有道理的;但是,如果目标是以类似于向DOM元素或函数添加属性但在未来永远不会发生冲突的方式将一些数据与DOM元素或功能关联起来,那么重点不是在map中添加map吗?

因此,上面mapF.set(updateFunc, {a: 5, b: 10})的代码示例应该是mapF.set(updateFunc, new Map( [ ['a', 5], ['b', 10] ] ) ),并且可以使用mapF.get(updateFunc).set('c', 20)添加属性(等等(。

但是,如果不使用两次get,就不能使用内部map。因此,看起来null object无论如何都将更容易被编码。

function myFunc() { };
var map_map = new Map([ [myFunc, new Map([ ['a',10], ['b',20]]) ] ] );
var obj = Object.create(null, {
a: { value: 10, enumerable: true },
b: { value: 20, enumerable: true }
});
var map_obj = new Map([[myFunc, obj]]);
console.log( map_map.get(myFunc).get('a') ); //=> 10
console.log( map_map.get(myFunc)['a'] ); //=> undefined
console.log( map_obj.get(myFunc).a); // => 10

当您在JS:中编写时

var funcInMap = function (x) { return x * 2; };

JS解释器创建了两个东西:

-1-对应于function (x) { return x * 2; }
的汇编代码,它将其放置在存储器地址@_memoryAddress_x1

-2-创建funcInMap变量,将内存地址@_memoryAddress_x1附加到该变量

随后您编码:

mapF.set('funcInMap',funcInMap);

JS解释器";变换";到
mapF.set('funcInMap', @_memoryAddress_x1);
,因为@_memoryAddress_x1funcInMap变量的内容匹配

updateFunc()中执行类似的操作:它为
function (x) { return x * 3; }
创建汇编代码,地址为@_memoryAddress_ZZ

并将funcInMap的值替换为@_memoryAddress_ZZ

但是地址CCD_ 32仍然存在
及其用于执行的汇编代码。

在类似的逻辑中(无需使用映射对象(

let
function_A = () => 'a'
, function_B = () => 'b'
, function_C = function_A
;
console.log( function_A() )   // return 'a'
console.log( function_C() )   // return 'a'
function_A = function_B
console.log( function_A() )   // return 'b'
console.log( function_C() )   // return 'a'

最新更新