[英]Undefined Property after new object construction using 'this' in constructor with self-executing function inside Object.defineProperty
I'm attempting to use a TypeScript-like structure to emulate an enumeration in a self-executing function for the 'value:' property. 我正在尝试使用一种类似TypeScript的结构来仿真“ value:”属性的自执行函数中的枚举。 I checked all over for examples of ECMAScript5 / Crockford Object.defineProperty() use in the constructor (using 'this') but could not find much.
我检查了所有在构造函数中使用ECMAScript5 / Crockford Object.defineProperty()的示例(使用'this'),但找不到太多。 As far as I can tell, the self-executing function should fill up both objects with 10 properties, and the closure is correct ('this' is not the window object).
据我所知,自执行函数应该用10个属性填充两个对象,并且闭包是正确的(“ this”不是window对象)。 Here's my design pattern:
这是我的设计模式:
var player = {};
var Foo = function () {
this.levelIndex;
Object.defineProperty(this, 'levelIndex', {
value: (function (levelIndex) {
levelIndex[levelIndex.ONE = 0] = 'ONE';
levelIndex[levelIndex.TWO = 1] = 'TWO';
levelIndex[levelIndex.THREE = 2] = 'THREE';
levelIndex[levelIndex.FOUR = 3] = 'FOUR';
levelIndex[levelIndex.FIVE = 4] = 'FIVE';
// setup the player object with the properties of the levelIndex
// before it becomes non-enumerable:
for (var i in levelIndex) {
Object.defineProperty(player, i, {
value: isNaN(levelIndex[i]) ? 'LEVEL_' + levelIndex[i] : levelIndex[i],
enumerable: false
});
alert(player[i]); //<-- LEVEL_ONE, LEVEL_TWO, LEVEL_THREE, LEVEL_FOUR, LEVEL_FIVE, 0, 1, 2, 3, 4
}
alert('window? : ' + this === window); //<-- false
})(this.levelIndex || (this.levelIndex = {})),
writable: false,
enumerable: false,
configurable: false
});
};
var foo = new Foo();
alert(player.ONE); //<-- 0
alert(foo.levelIndex); //<-- undefined
alert(foo.levelIndex.ONE); //<-- Uncaught TypeError: Cannot read property 'ONE' of undefined
Why is foo.levelIndex
undefined here? 为什么在这里未定义
foo.levelIndex
?
EDIT: Fixed with return levelIndex;
编辑:固定与
return levelIndex;
added to anonymous function call. 添加到匿名函数调用中。
Any comments on my design pattern or suggestions for improvement welcome! 欢迎对我的设计模式提出任何意见或提出改进建议!
You're calling the anonymous function with a plain function call, so the value of this
will be undefined
in strict mode, or the global object ( window
) otherwise. 你调用一个普通的函数调用的匿名函数,所以价值
this
将undefined
严格模式,或全局对象( window
),否则。 What it definitely won't be is a reference to the object literal you're defining. 绝对不会是对您所定义的对象文字的引用。
The first line of your "Foo" function looks a little suspicious: 您的“ Foo”功能的第一行看起来有点可疑:
this.levelIndex;
That will have no effect on anything; 那将不会对任何事物产生影响; specifically, it will not cause there to be a property named "levelIndex" created on the object referenced by
this
. 具体而言,也不会造成那里是一个名为“levelIndex”被引用的对象上创建属性
this
。
edit — also, as I look more at what you're doing, it's pretty clear why the "levelIndex" property ends up undefined
: that object literal has a "value" property that's set to the return value of that anonymous function call. 编辑 -同样,当我更多地查看您的操作时,很清楚为什么“ levelIndex”属性最终
undefined
:该对象文字具有一个“ value”属性,该属性设置为该匿名函数调用的返回值。 The anonymous function, however, has no return
statement, so the call to Object.defineProperty
involves a property object with the "value" property set to undefined
. 但是,匿名函数没有
return
语句,因此对Object.defineProperty
的调用涉及一个属性对象,该属性对象的“值”属性设置为undefined
。 If you add 如果添加
return levelIndex;
to the end of that anonymous function, it ( might ) work. 到该匿名函数的末尾,它( 可能 )有效。 (I think it would.)
(我认为是。)
Based on help from @Pointy and @Bergi, here is the updated working code: 基于@Pointy和@Bergi的帮助,以下是更新的工作代码:
http://jsfiddle.net/5j9W5/ http://jsfiddle.net/5j9W5/
var player = {};
var Foo = function () {
Object.defineProperty(this, 'levelIndex', {
value: (function (levelIndex) {
levelIndex[levelIndex.ONE = 0] = 'ONE';
levelIndex[levelIndex.TWO = 1] = 'TWO';
levelIndex[levelIndex.THREE = 2] = 'THREE';
levelIndex[levelIndex.FOUR = 3] = 'FOUR';
levelIndex[levelIndex.FIVE = 4] = 'FIVE';
return levelIndex;
})(this.levelIndex || (this.levelIndex = {})),
writable: false,
enumerable: false,
configurable: false
});
// setup the player object with the properties of the levelIndex:
for (var i in this.levelIndex) {
Object.defineProperty(player, i, {
value: isNaN(this.levelIndex[i]) ? 'LEVEL_' + this.levelIndex[i] : this.levelIndex[i],
enumerable: false
});
}
};
var foo = new Foo();
alert(player[0]); //<-- LEVEL_ONE
alert(foo.levelIndex.FIVE); //<-- 4
for (var i in player) {
alert(i + ' ' + player[i]); //<-- no output (properties are not enumerable here)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.