답변:
글쎄, 내가 말할 수있는 유일한 것은 게터입니다 .
var foo = {
a: 5,
b: 6,
get c() {
return this.a + this.b;
}
}
console.log(foo.c) // 11
이것은 ECMAScript 5th Edition Specification에 의해 도입 된 구문 확장이며, 구문은 대부분의 최신 브라우저 (IE9 포함)에서 지원됩니다.
foo.a
또는 의 값 foo.b
이 변경 되면이 솔루션의 값 foo.c
도 동기화되어 변경됩니다. 필요한 것일 수도 있고 아닐 수도 있습니다.
this
깊은 중첩 된 객체에 바인드를. 예 :... x: { get c () { /*this is x, not foo*/ } } ...
foo
꿀벌은 변수로 선언되어 있고 c
호출 될 때만 평가 될 것이기 때문에, foo
내부 c
는 this
(주의해야합니다) 반대로 작동합니다
당신은 다음과 같은 것을 할 수 있습니다 :
var foo = {
a: 5,
b: 6,
init: function() {
this.c = this.a + this.b;
return this;
}
}.init();
이것은 일종의 객체 초기화 일 것입니다.
실제로의 반환 값을 init()
에 지정하고 있으므로을 (를) 지정 foo
해야합니다 return this
.
delete this.init
전에 할 수 있습니다return this
foo
init()
을 유지하기 위해 리터럴이 직접 리터럴에 추가되었습니다. 그러나 물론 원하는대로 함수를 호출 할 수 있습니다.
명확하고 간단한 대답이 누락되었으므로 완전성을 위해 다음을 수행하십시오.
그러나 인 객체 리터럴의 속성 값을 가질 수있는 방법이 선언 이전이 다른 속성에 따라 달라집니다?
아니요. 여기에있는 모든 솔루션은 객체가 생성 될 때까지 (다양한 방식으로) 지연된 다음 세 번째 속성을 할당합니다. 가장 간단한 방법은이 작업을 수행하는 것입니다 :
var foo = {
a: 5,
b: 6
};
foo.c = foo.a + foo.b;
다른 모든 사람들은 같은 일을하는 간접적 인 방법 일뿐입니다. (Felix는 특히 영리하지만 임시 기능을 생성 및 파괴하여 복잡성을 추가해야하며, 객체에 추가 속성을 남겨 두거나 [ delete
해당 속성이있는 경우] 해당 객체에 대한 후속 속성 액세스 의 성능 에 영향을 미칩니다 .)
모두 하나의 표현식 내에 있어야하는 경우 임시 속성없이이를 수행 할 수 있습니다.
var foo = function(o) {
o.c = o.a + o.b;
return o;
}({a: 5, b: 6});
또는이 작업을 두 번 이상 수행해야하는 경우 :
function buildFoo(a, b) {
var o = {a: a, b: b};
o.c = o.a + o.b;
return o;
}
그런 다음 어디에 사용해야합니까?
var foo = buildFoo(5, 6);
this
는 해당 객체의 메소드 에서만 사용할 수 있으며 다른 종류의 속성 은 사용할 수 없습니다. 어디서 찾을 수 있을지 아십니까? 감사!
익명 함수를 간단히 인스턴스화하십시오.
var foo = new function () {
this.a = 5;
this.b = 6;
this.c = this.a + this.b;
};
new Point(x, y)
함수의 이름이 재사용을 위해 지정되지 않았다는 점을 제외하고 는 인수를 전달하는 것과 다르지 않습니다.
var foo = function() { this.…; return this; }.call({});
구문 상 크게 다르지 않지만 의미 적으로 제정신 인 것을 사용하십시오.
new
키워드를 눈치 채지 못했다 .
이제 ES6에서는 지연 캐시 속성을 생성 할 수 있습니다. 처음 사용할 때이 속성은 한 번 평가되어 일반 정적 속성이됩니다. 결과 : 두 번째로 수학 함수 오버 헤드를 건너 뜁니다.
마술은 게터에있다.
const foo = {
a: 5,
b: 6,
get c() {
delete this.c;
return this.c = this.a + this.b
}
};
화살표에서 getter this
는 주변 어휘 범위를 선택합니다 .
foo // {a: 5, b: 6}
foo.c // 11
foo // {a: 5, b: 6 , c: 11}
Object.defineProperty(foo, 'c', {get:function() {...}})
를 정의하는 데 사용해야 하는 속성이 있습니다. 이것은 이와 같은 공장에서 눈에 거슬리지 않게 쉽게 수행됩니다. 물론 get
설탕을 사용할 수 있다면 설탕을 더 잘 읽을 수 있지만 그 능력이 있습니다.
일부 폐쇄는이 문제를 처리해야합니다.
var foo = function() {
var a = 5;
var b = 6;
var c = a + b;
return {
a: a,
b: b,
c: c
}
}();
함수 선언에서 기대할 수있는 것처럼 내부 foo
에 선언 된 모든 변수 는 private에 foo
있으며 범위 내에 있기 때문에 함수에서 this
예상하는 것처럼 참조 할 필요없이 서로에 액세스 할 수 있습니다. 차이점은이 함수는 전용 변수를 노출하고 해당 객체를에 할당하는 객체를 반환한다는 것입니다 foo
. 결국, 당신은 return {}
문장으로 객체로서 노출시키고 자하는 인터페이스만을 반환한다 .
그런 다음 함수는 마지막으로 실행되어 ()
전체 foo 객체가 평가되고 인스턴스화 된 모든 변수가의 속성으로 추가됩니다 foo()
.
당신은 이렇게 할 수 있습니다
var a, b
var foo = {
a: a = 5,
b: b = 6,
c: a + b
}
이 방법은 함수가 원래 선언 된 객체를 참조해야 할 때 유용하다는 것이 입증되었습니다. 다음은 내가 어떻게 사용했는지에 대한 최소한의 예입니다.
function createMyObject() {
var count = 0, self
return {
a: self = {
log: function() {
console.log(count++)
return self
}
}
}
}
인쇄 기능이 포함 된 객체로 self를 정의하면 해당 함수가 해당 객체를 참조 할 수 있습니다. 즉, 인쇄 기능을 다른 곳에 전달해야하는 경우 인쇄 기능을 객체에 '바인드'할 필요가 없습니다.
대신 this
아래 그림과 같이 사용하십시오
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!
자체 방법을 사용하면 함수가 실행되는 컨텍스트에 관계없이 print가 항상 동일한 객체를 반환합니다. 위의 코드는 자체 버전을 사용할 때 정상적으로 실행되고 0, 1, 2 및 3을 기록 createMyObject()
합니다.
모듈 패턴을 사용하여 수행 할 수 있습니다. 처럼:
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
이 패턴을 사용하면 필요에 따라 여러 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
생각을 위해서-타임 라인에서 객체의 속성을 배치하십시오.
var foo = {
a: function(){return 5}(),
b: function(){return 6}(),
c: function(){return this.a + this.b}
}
console.log(foo.c())
위에 더 나은 답변이 있습니다 . 이것이 내가 질문 한 예제 코드를 수정 한 방법입니다.
최신 정보:
var foo = {
get a(){return 5},
get b(){return 6},
get c(){return this.a + this.b}
}
// console.log(foo.c);
객체 리터럴에서 새 함수를 만들고 생성자를 호출하면 원래 문제에서 근본적으로 벗어난 것처럼 보이므로 불필요합니다.
객체 리터럴 초기화 중에 형제 속성을 참조 할 수 없습니다.
var x = { a: 1, b: 2, c: a + b } // not defined
var y = { a: 1, b: 2, c: y.a + y.b } // not defined
계산 된 속성에 대한 가장 간단한 솔루션은 다음과 같습니다 (힙 없음, 함수 없음, 생성자 없음).
var x = { a: 1, b: 2 };
x.c = x.a + x.b; // apply computed property
여기에 게시 된 다른 답변이 더 좋지만 다음과 같은 대안이 있습니다.
init()
객체 리터럴 이외의 유형 이나 코드가 필요하지 않습니다.자체 실행 익명 기능 및 창 저장
var foo = {
bar:(function(){
window.temp = "qwert";
return window.temp;
})(),
baz: window.temp
};
주문이 보장됩니다 ( bar
이전 baz
).
window
물론 오염 이 발생하지만 누군가 window.temp
가 지속적이어야 하는 스크립트를 작성하는 것을 상상할 수 없습니다 . 아마도 tempMyApp
당신이 편집증이라면.
또한 추악하지만 때로는 유용합니다. 예를 들어 엄격한 초기화 조건을 가진 API를 사용하고 리팩토링을 느끼지 않기 때문에 범위가 정확합니다.
그리고 물론 건조합니다.
이 모든 것의 핵심은 SCOPE 입니다.
자신의 인스턴스화 된 객체로 정의하려는 속성의 "부모"(부모 개체)를 캡슐화 한 다음 키워드를 사용하여 형제 속성에 대한 참조를 만들 수 있습니다. this
먼저 그렇게하지 않고 참조하면 외부 범위 를 참조한다는 것을 기억하는 것이 매우 중요 합니다. 이것이 대상 이 될 것 입니다.this
this
window
var x = 9 //this is really window.x
var bar = {
x: 1,
y: 2,
foo: new function(){
this.a = 5, //assign value
this.b = 6,
this.c = this.a + this.b; // 11
},
z: this.x // 9 (not 1 as you might expect, b/c *this* refers `window` object)
};
객체가 객체를 반환하는 함수로 작성되고 ES6 객체 속성 '방법'을 사용하는 경우 가능합니다.
const module = (state) => ({
a: 1,
oneThing() {
state.b = state.b + this.a
},
anotherThing() {
this.oneThing();
state.c = state.b + this.a
},
});
const store = {b: 10};
const root = module(store);
root.oneThing();
console.log(store);
root.anotherThing();
console.log(store);
console.log(root, Object.keys(root), root.prototype);
깔끔한 ES6 방법은 다음과 같습니다.
var foo = (o => ({
...o,
c: o.a + o.b
}))({
a: 5,
b: 6
});
console.log(foo);
나는 이것을 다음과 같이하기 위해 사용한다 :
const constants = Object.freeze(
(_ => ({
..._,
flag_data: {
[_.a_flag]: 'foo',
[_.b_flag]: 'bar',
[_.c_flag]: 'oof'
}
}))({
a_flag: 5,
b_flag: 6,
c_flag: 7,
})
);
console.log(constants.flag_data[constants.b_flag]);
이 솔루션은 배열이있는 중첩 된 객체에서도 작동합니다.
Object.prototype.assignOwnProVal
= function (to,from){
function compose(obj,string){
var parts = string.split('.');
var newObj = obj[parts[0]];
if(parts[1]){
parts.splice(0,1);
var newString = parts.join('.');
return compose(newObj,newString);
}
return newObj;
}
this[to] = compose(this,from);
}
var obj = { name : 'Gaurav', temp :
{id : [10,20], city:
{street:'Brunswick'}} }
obj.assignOwnProVal('street','temp.city.street');
obj.assignOwnProVal('myid','temp.id.1');
이 정확한 시나리오가 다루어지지 않았기 때문에 옵션을 던졌습니다. 당신이 경우 하지 않는 원하는 c
경우 업데이트 a
또는 b
업데이트 후 ES6 인생은 잘 작동합니다.
var foo = ((a,b) => ({
a,
b,
c: a + b
}))(a,b);
내 필요에 따라 루프에서 사용되는 배열과 관련된 객체가 있으므로 일반적인 설정을 한 번만 계산하고 싶으므로 이것이 내가 가진 것입니다.
let processingState = ((indexOfSelectedTier) => ({
selectedTier,
indexOfSelectedTier,
hasUpperTierSelection: tiers.slice(0,indexOfSelectedTier)
.some(t => pendingSelectedFiltersState[t.name]),
}))(tiers.indexOf(selectedTier));
속성을 설정해야하고 속성을 설정할 indexOfSelectedTier
때 해당 값을 사용해야하므로 hasUpperTierSelection
먼저 해당 값을 계산하여 IIFE의 매개 변수로 전달합니다
다른 접근 방식은 속성을 할당하기 전에 먼저 객체를 선언하는 것입니다.
const foo = {};
foo.a = 5;
foo.b = 6;
foo.c = foo.a + foo.b; // Does work
foo.getSum = () => foo.a + foo.b + foo.c; // foo.getSum() === 22
이를 통해 객체 변수 이름을 사용하여 이미 할당 된 값에 액세스 할 수 있습니다. 파일에
가장 적합 config.js
합니다.
foo
문제의 객체를 가리키는 선언 된 변수 에 대한 참조입니다.
참고 : 이 솔루션은 Typescript를 사용합니다 (필요한 경우 TS가 컴파일하는 vanilla JS를 사용할 수 있음)
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();
여기에 클래스 표현식을 사용하여 원하는 중첩 객체 리터럴 인터페이스를 얻었습니다. 이것이 IMHO가 만드는 동안 객체의 속성을 참조 할 수있는 다음 가장 좋은 것입니다.
주목해야 할 것은이 솔루션을 사용하는 동안 객체 리터럴에서와 동일한 인터페이스를 사용한다는 것입니다. 그리고 구문은 객체 리터럴 자체에 가깝습니다 (함수 사용 등).
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';
};
}
}
네이티브 JS를 사용하려면 다른 답변이 좋은 솔루션을 제공합니다.
그러나 다음과 같은 자체 참조 객체를 작성하려는 경우 :
{
a: ...,
b: "${this.a + this.a}",
}
해당 구문을 지원하고 기본 객체를 반환하는 self-referenced-object 라는 npm 라이브러리를 작성했습니다 .
b
부동산 가치는 다음과 같아야합니다 ${this.a + this.a}
. 둘째, 덜 중요하게는과 같은 것을 사용하여 문자열이 아닌 숫자를 반환하려고합니다 parseInt
. 마지막으로 가장 중요한 것은이 예제를 시도했을 때 OP가 요구하는 것과 같은 이유로 작동하지 않습니다. this
자신의 객체 선언을 사용하는 경우 undefined를 반환합니다. @ alex-e-leon