[javascript] 객체 리터럴 / 이니셜 라이저의 자체 참조

JavaScript에서 다음과 같은 작업을 수행하는 방법이 있습니까?

var foo = {
    a: 5,
    b: 6,
    c: this.a + this.b  // Doesn't work
};

현재 양식에서이 코드는 참조 this하지 않기 때문에 참조 오류가 발생 합니다 foo. 그러나 객체 리터럴의 속성 값을 가질 수있는 방법이 선언 이전이 다른 속성에 따라 달라집니다?



답변

글쎄, 내가 말할 수있는 유일한 것은 게터입니다 .

var foo = {
  a: 5,
  b: 6,
  get c() {
    return this.a + this.b;
  }
}

console.log(foo.c) // 11

이것은 ECMAScript 5th Edition Specification에 의해 도입 된 구문 확장이며, 구문은 대부분의 최신 브라우저 (IE9 포함)에서 지원됩니다.


답변

당신은 다음과 같은 것을 할 수 있습니다 :

var foo = {
   a: 5,
   b: 6,
   init: function() {
       this.c = this.a + this.b;
       return this;
   }
}.init();

이것은 일종의 객체 초기화 일 것입니다.

실제로의 반환 값을 init()에 지정하고 있으므로을 (를) 지정 foo해야합니다 return this.


답변

명확하고 간단한 대답이 누락되었으므로 완전성을 위해 다음을 수행하십시오.

그러나 객체 리터럴의 속성 값을 가질 수있는 방법이 선언 이전이 다른 속성에 따라 달라집니다?

아니요. 여기에있는 모든 솔루션은 객체가 생성 될 때까지 (다양한 방식으로) 지연된 다음 세 번째 속성을 할당합니다. 가장 간단한 방법은이 작업을 수행하는 것입니다 :

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);

답변

익명 함수를 간단히 인스턴스화하십시오.

var foo = new function () {
    this.a = 5;
    this.b = 6;
    this.c = this.a + this.b;
};

답변

이제 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}  

답변

일부 폐쇄는이 문제를 처리해야합니다.

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()합니다.