kpo*_*zin 660 javascript object-literal
有没有办法在JavaScript中使用以下内容?
var foo = {
a: 5,
b: 6,
c: this.a + this.b // Doesn't work
};
Run Code Online (Sandbox Code Playgroud)
在当前形式中,此代码显然会抛出引用错误,因为this没有引用foo.但是,是有什么办法对早些时候宣布的其他属性在对象文本的属性值依赖?
CMS*_*CMS 676
好吧,我唯一可以告诉你的是吸气剂:
var foo = {
a: 5,
b: 6,
get c() {
return this.a + this.b;
}
}
console.log(foo.c) // 11Run Code Online (Sandbox Code Playgroud)
这是ECMAScript第5版规范引入的语法扩展,大多数现代浏览器(包括IE9)都支持该语法.
Fel*_*ing 303
你可以这样做:
var foo = {
a: 5,
b: 6,
init: function() {
this.c = this.a + this.b;
return this;
}
}.init();
Run Code Online (Sandbox Code Playgroud)
这将是对象的某种一次初始化.
请注意,你实际上是分配的返回值init()来foo,所以你必须return this.
T.J*_*der 167
缺少明显的简单答案,所以为了完整性:
但是,是有什么办法对早些时候宣布的其他属性在对象文本的属性值依赖?
不会.这里的所有解决方案都会推迟到创建对象之后(以各种方式),然后分配第三个属性.在最简单的方法是只是这样做:
var foo = {
a: 5,
b: 6
};
foo.c = foo.a + foo.b;
Run Code Online (Sandbox Code Playgroud)
所有其他人只是更间接的方式来做同样的事情.(Felix's特别聪明,但需要创建和销毁临时函数,增加复杂性;要么在对象上留下额外的属性,要么[如果你的delete属性] 影响对该对象的后续属性访问的性能.)
如果你需要它在一个表达式中,你可以在没有临时属性的情况下做到这一点:
var foo = function(o) {
o.c = o.a + o.b;
return o;
}({a: 5, b: 6});
Run Code Online (Sandbox Code Playgroud)
或者当然,如果您需要多次执行此操作:
function buildFoo(a, b) {
var o = {a: a, b: b};
o.c = o.a + o.b;
return o;
}
Run Code Online (Sandbox Code Playgroud)
然后你需要使用它:
var foo = buildFoo(5, 6);
Run Code Online (Sandbox Code Playgroud)
zzz*_*Bov 60
只需实例化一个匿名函数:
var foo = new function () {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
};
Run Code Online (Sandbox Code Playgroud)
vos*_*usa 23
现在在ES6中,您可以创建惰性缓存属性.首次使用时,属性将评估一次以成为正常的静态属性.结果:第二次跳过数学函数开销.
魔法在吸气剂中.
const foo = {
a: 5,
b: 6,
get c() {
delete this.c;
return this.c = this.a + this.b
}
};
Run Code Online (Sandbox Code Playgroud)
在箭头中,getter this拾取周围的词法范围.
foo // {a: 5, b: 6}
foo.c // 11
foo // {a: 5, b: 6 , c: 11}
Run Code Online (Sandbox Code Playgroud)
小智 20
有些关闭应该处理这个问题;
var foo = function() {
var a = 5;
var b = 6;
var c = a + b;
return {
a: a,
b: b,
c: c
}
}();
Run Code Online (Sandbox Code Playgroud)
在内部声明的所有变量foo都是私有的foo,正如您对任何函数声明所期望的那样,并且因为它们都在范围内,所以它们都可以相互访问而无需引用this,就像您对函数所期望的那样.区别在于此函数返回一个公开私有变量并将该对象分配给的对象foo.最后,只返回要作为对象公开的接口return {}.
然后在最后执行该函数,()其中导致整个foo对象被评估,实例化中的所有变量和作为属性添加的返回对象foo().
dav*_*ite 15
你可以这样做
var a, b
var foo = {
a: a = 5,
b: b = 6,
c: a + b
}
Run Code Online (Sandbox Code Playgroud)
当我不得不引用最初声明函数的对象时,该方法对我有用.以下是我如何使用它的最小例子:
function createMyObject() {
var count = 0, self
return {
a: self = {
log: function() {
console.log(count++)
return self
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
通过将self定义为包含print函数的对象,您可以让函数引用该对象.这意味着如果您需要将打印功能传递给其他地方,则不必将打印功能"绑定"到对象上.
相反,如果您愿意,请this按照下图所示使用
function createMyObject() {
var count = 0
return {
a: {
log: function() {
console.log(count++)
return this
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,以下代码将记录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!
Run Code Online (Sandbox Code Playgroud)
通过使用self方法,您可以保证print始终返回相同的对象,而不管运行函数的上下文如何.上面的代码运行得很好,并在使用自我版本时记录0,1,2和3 createMyObject().
为了完成,在ES6中我们有类(在撰写本文时仅支持最新的浏览器,但在Babel,TypeScript和其他转换器中可用)
class Foo {
constructor(){
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
}
}
const foo = new Foo();
Run Code Online (Sandbox Code Playgroud)
您可以使用模块模式执行此操作.就像:
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
Run Code Online (Sandbox Code Playgroud)
使用此模式,您可以根据需要实例化几个foo对象.
有几种方法可以实现这一目标; 这是我会用的:
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
Run Code Online (Sandbox Code Playgroud)
只是为了思考 - 在时间轴之外放置对象的属性:
var foo = {
a: function(){return 5}(),
b: function(){return 6}(),
c: function(){return this.a + this.b}
}
console.log(foo.c())
Run Code Online (Sandbox Code Playgroud)
上面也有更好的答案.这就是我修改你质疑的示例代码的方法.
更新:
var foo = {
get a(){return 5},
get b(){return 6},
get c(){return this.a + this.b}
}
// console.log(foo.c);
Run Code Online (Sandbox Code Playgroud)
该get属性效果很好,您还可以对“昂贵”的函数使用绑定闭包,该函数只应运行一次(这只适用于var,不适用于constor let)
var info = {
address: (function() {
return databaseLookup(this.id)
}).bind(info)(),
get fullName() {
console.log('computing fullName...')
return `${this.first} ${this.last}`
},
id: '555-22-9999',
first: 'First',
last: 'Last',
}
function databaseLookup() {
console.log('fetching address from remote server (runs once)...')
return Promise.resolve(`22 Main St, City, Country`)
}
// test
(async () => {
console.log(info.fullName)
console.log(info.fullName)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
console.log(await info.address)
})()Run Code Online (Sandbox Code Playgroud)
小智 6
仅供大家娱乐:
var foo = ( (This={
a: 5,
b: 6, })=>({...This,
c: This.a + This.b }))(
);
console.log(foo);Run Code Online (Sandbox Code Playgroud)
在对象文字上创建新函数并调用构造函数似乎与原始问题大相径庭,这是不必要的。
在对象文字初始化期间,您不能引用同级属性。
var x = { a: 1, b: 2, c: a + b } // not defined
var y = { a: 1, b: 2, c: y.a + y.b } // not defined
Run Code Online (Sandbox Code Playgroud)
计算属性的最简单解决方案如下(没有堆,没有函数,没有构造函数):
var x = { a: 1, b: 2 };
x.c = x.a + x.b; // apply computed property
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
122260 次 |
| 最近记录: |