function createMyObject() {
var count = 0
return {
a: {
log: function() {
console.log(count++)
return this
}
}
}
}
然后,以下代码将记录0,1,2,然后给出错误
var o = createMyObject()
var log = o.a.log
o.a.log().log() // this refers to the o.a object so the chaining works
log().log() // this refers to the window object so the chaining fails!
function Obj() {
this.a = 5;
this.b = this.a + 1;
// return this; // commented out because this happens automatically
}
var o = new Obj();
o.b; // === 6
287
您可以使用模块模式执行此操作 . 就像:
var foo = function() {
var that = {};
that.a = 7;
that.b = 6;
that.c = function() {
return that.a + that.b;
}
return that;
};
var fooObject = foo();
fooObject.c(); //13
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
// this method is just to check/test this solution
check(){
console.log(this.def.qwe);
}
}
// these two lines are just to check
let instance = new asd();
instance.check();
class asd {
def = new class {
ads= 'asd';
qwe= this.ads + '123';
};
解决方案,如果对象文字已经足够了
var asd = {
def : {
ads:'asd',
qwe: this.ads + '123';, //ILLEGAL CODE; just to show ideal scenario
}
}
另一个例子
在这个类中,您可以在它们之间组合多个相对路径,这对于对象文字是不可能的 .
class CONSTANT {
static readonly PATH = new class {
/** private visibility because these relative paths don't make sense for direct access, they're only useful to path class
*
*/
private readonly RELATIVE = new class {
readonly AFTER_EFFECTS_TEMPLATE_BINARY_VERSION: fs.PathLike = '\\assets\\aep-template\\src\\video-template.aep';
readonly AFTER_EFFECTS_TEMPLATE_XML_VERSION: fs.PathLike = '\\assets\\aep-template\\intermediates\\video-template.aepx';
readonly RELATIVE_PATH_TO_AFTER_EFFECTS: fs.PathLike = '\\Adobe\\Adobe After Effects CC 2018\\Support Files\\AfterFX.exe';
readonly OUTPUT_DIRECTORY_NAME: fs.PathLike = '\\output';
readonly INPUT_DIRECTORY_NAME: fs.PathLike = '\\input';
readonly ASSETS_DIRECTORY_NAME: fs.PathLike = '\\assets';
};
}
}
21 回答
好吧,我唯一可以告诉你的是吸气剂:
这是ECMAScript第5版规范引入的语法扩展,大多数现代浏览器(包括IE9)都支持该语法 .
你可以这样做:
这将是对象的某种一次初始化 .
请注意,您实际上是将
init()
的返回值分配给foo
,因此您必须return this
.缺少明显的简单答案,所以为了完整性:
不会 . 这里的所有解决方案都会推迟到创建对象之后(以各种方式),然后分配第三个属性 . 最简单的方法就是这样做:
所有其他人只是更间接的方式来做同样的事情 . (Felix's特别聪明,但需要创建和销毁临时函数,增加复杂性;要么在对象上留下额外的属性,要么[如果你
delete
属性] impacts the performance后续属性访问该对象 . )如果你需要它在一个表达式中,你可以在没有临时属性的情况下做到这一点:
或者当然,如果您需要多次执行此操作:
然后你需要使用它:
只需实例化一个匿名函数:
有些关闭应该处理这个问题;
在
foo
中声明的所有变量都是foo
的私有,正如您对任何函数声明所期望的那样,并且因为它们都在范围内,所以它们都可以相互访问而无需引用this
,就像您对函数所期望的那样 . 区别在于此函数返回一个公开私有变量的对象,并将该对象分配给foo
. 最后,只返回要作为具有return {}
语句的对象公开的接口 .然后使用
()
在最后执行该函数,这将导致整个foo对象被评估,实例化中的所有变量和作为foo()
的属性添加的返回对象 .现在在ES6中,您可以创建惰性缓存属性 . 首次使用时,属性将评估一次以成为正常的静态属性 . 结果:第二次跳过数学函数开销 .
魔法在吸气剂中 .
在箭头getter
this
拿起surrounding lexical scope .你可以这样做
当我不得不引用最初声明函数的对象时,该方法对我有用 . 以下是我如何使用它的最小例子:
通过将self定义为包含print函数的对象,您可以让函数引用该对象 . 这意味着如果您需要将打印功能传递给其他地方,则不必将打印功能“绑定”到对象上 .
相反,如果您愿意,请使用
this
,如下图所示然后,以下代码将记录0,1,2,然后给出错误
通过使用self方法,您可以保证print始终返回相同的对象,而不管运行函数的上下文 . 当使用
createMyObject()
的自我版本时,上面的代码将运行正常并记录0,1,2和3 .为了完成,在ES6中我们有类(在撰写时仅支持最新的浏览器,但在Babel,TypeScript和其他转换器中可用)
有几种方法可以实现这一目标;这是我会用的:
您可以使用模块模式执行此操作 . 就像:
使用此模式,您可以根据需要实例化几个foo对象 .
http://jsfiddle.net/jPNxY/1/
只是为了思考 - 在时间轴之外放置对象的属性:
上面也有更好的答案 . 这就是我修改你所质疑的示例代码的方法 .
UPDATE:
在对象文字上创建新函数并调用构造函数似乎与原始问题完全不同,并且它是不必要的 .
在对象文字初始化期间,您无法引用同级属性 .
计算属性的最简单解决方案如下(没有堆,没有函数,没有构造函数):
这一切的关键是 SCOPE .
您需要封装要定义的属性的"parent"(父对象)作为它自己的实例化对象,然后您可以使用关键字
this
来引用兄弟属性要记住,如果你在没有这么做的情况下引用
this
,那么this
将引用外部范围......这将是window
对象 .这里发布的其他答案更好,但这里有一个替代方案:
设置初始化时的值(不是getter或派生等)
不需要任何类型的
init()
或对象文字之外的代码是对象文字,而不是工厂函数或其他对象创建机制 .
不应对性能产生任何影响(初始化除外)
Self-executing anonymous functions and window storage
订单是guaranteed(在
baz
之前bar
) .它当然会污染
window
,但我无法想象有人编写需要window.temp
持久的脚本 . 如果你是偏执狂,也许tempMyApp
它也很难看,但偶尔也很有用 . 例如,当您使用具有严格初始化条件的API并且不想重构时,因此范围是正确的 .
当然,它很干燥 .
如果您的对象被写为返回对象的函数,并且您使用ES6对象属性'methods',则可能:
这是一个整洁的ES6方式:
我用它来做这样的事情:
这个解决方案怎么样也适用于带有数组的嵌套对象
我使用以下代码作为替代,它的工作原理 . 变量也可以是数组 . (@ Fausto R.)
投入选项,因为我没有看到这个确切的情况 . 如果您不想在
a
或b
更新时更新c
,则ES6 IIFE运行良好 .根据我的需要,我有一个与最终用于循环的数组有关的对象,所以我只想计算一次常用设置,所以这就是我所拥有的:
因为我需要为
indexOfSelectedTier
设置一个属性,我需要在设置hasUpperTierSelection
属性时使用该值,我首先计算该值并将其作为参数传递给IIFE另一种方法是保持原始对象的属性,使用第一个对象属性的动态属性创建第二个对象,然后使用spread进行合并 .
所以:
Object
Object 2
Merge
要么
Result of foo:
所有在同一个js内,对象内没有新功能,只使用赋值或传播 .
这里使用类表达式来获取我们想要的嵌套对象文字界面 . 这是IMHO在创建过程中能够引用对象属性的下一个最好的事情 .
需要注意的主要事项是在使用此解决方案时,您拥有与对象文字完全相同的界面 . 语法非常接近对象文字本身(与使用函数等) .
比较以下内容
我提出的解决方案
解决方案,如果对象文字已经足够了
另一个例子
在这个类中,您可以在它们之间组合多个相对路径,这对于对象文字是不可能的 .