이제 DOM 속성이 프로토타입 체인에 추가됨

Chrome팀은 최근 DOM 속성을 프로토타입 체인으로 이전한다고 발표했습니다. Chrome 43(2015년 4월 중순 베타 버전)에 구현된 이 변경사항으로 Chrome이 웹 IDL 사양 및 IE, Firefox 등 다른 브라우저의 구현에 더 부합하도록 할 수 있습니다. 수정: 설명 이전 WebKit 기반 브라우저는 현재 사양과 호환되지 않지만 Safari는 현재 지원됩니다.

새로운 행동은 여러 면에서 긍정적입니다. 담고 있습니다.

  • 사양 준수를 통해 웹 간의 호환성을 개선합니다 (IE 및 Firefox는 이미 지원함).
  • 모든 DOM 객체에 getter/setter를 일관되고 효율적으로 생성할 수 있습니다.
  • DOM 프로그래밍의 해킹 가능성이 증가합니다. 예를 들어, 기본 DOM 속성 동작을 재정의하는 일부 브라우저와 JavaScript 라이브러리에서 누락된 기능을 효율적으로 에뮬레이션할 수 있는 폴리필을 구현할 수 있습니다.

예를 들어 가상의 W3C 사양에는 isSuperContentEditable이라는 새 기능이 포함되어 있고 Chrome 브라우저는 이를 구현하지 않지만, 라이브러리를 사용하여 기능을 '폴리필'하거나 에뮬레이션할 수는 있습니다. 라이브러리 개발자는 다음과 같이 prototype를 사용하여 효율적인 폴리필을 만드는 것이 좋습니다.

Object.defineProperty(HTMLDivElement.prototype, "isSuperContentEditable", {
    get: function() { return true; },
    set: function() { /* some logic to set it up */ },
});

이 변경사항이 적용되기 전에는 Chrome의 다른 DOM 속성과의 일관성을 위해 모든 인스턴스에서 새 속성을 만들어야 했으며, 이 경우 페이지의 모든 HTMLDivElement에 대해 매우 비효율적입니다.

이러한 변경사항은 웹 플랫폼의 일관성, 성능 및 표준화에 중요하지만 개발자에게 몇 가지 문제를 일으킬 수 있습니다. Chrome과 WebKit 간의 기존 호환성 때문에 이 동작을 사용하고 있었다면 사이트를 확인하고 아래에서 변경사항 요약을 확인하시기 바랍니다.

변경사항 요약

이제 DOM 객체 인스턴스에서 hasOwnProperty를 사용하면 false가 반환됩니다.

개발자는 hasOwnProperty를 사용하여 객체에 속성이 있는지 확인합니다. 이제 DOM 속성이 프로토타입 체인의 일부이고 hasOwnProperty가 현재 객체에만 정의되어 있는지 확인하기 위해 검사하므로 이는 더 이상 사양에 따라 작동하지 않습니다.

Chrome 42 및 이전 버전에서는 다음과 같이 true이 반환되었습니다.

> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");

true

Chrome 43 이상에서는 false를 반환합니다.

> div = document.createElement("div");
> div.hasOwnProperty("isContentEditable");

false

즉, 요소에서 isContentEditable를 사용할 수 있는지 확인하려면 HTMLElement 객체에서 프로토타입을 확인해야 합니다. 예를 들어 HTMLDivElementisContentEditable 속성을 정의하는 HTMLElement에서 상속받습니다.

> HTMLElement.prototype.hasOwnProperty("isContentEditable");

true

hasOwnProperty을(를) 사용하도록 설정되어 있지 않습니다. 훨씬 더 간단한 in 피연산자를 사용하는 것이 좋습니다. 이 피연산자는 전체 프로토타입 체인의 속성을 확인하기 때문입니다.

if("isContentEditable" in div) {
    // We have support!!
}

DOM 객체 인스턴스의 Object.getOwnPropertyDescriptor가 더 이상 속성의 속성 설명자를 반환하지 않습니다.

사이트에서 DOM 객체의 속성에 대한 속성 설명자를 가져와야 하는 경우, 이제 프로토타입 체인을 따라야 합니다.

Chrome 42 이하에서 속성 설명을 가져오려면 다음 단계를 따르세요.

> Object.getOwnPropertyDescriptor(div, "isContentEditable");

Object {value: "", writable: true, enumerable: true, configurable: true}

이 시나리오에서는 Chrome 43 이상에서는 undefined가 반환됩니다.

> Object.getOwnPropertyDescriptor(div, "isContentEditable");

undefined

즉, isContentEditable 속성의 속성 설명자를 가져오려면 다음과 같이 프로토타입 체인을 따라야 합니다.

> Object.getOwnPropertyDescriptor(HTMLElement.prototype, "isContentEditable");

Object {get: function, set: function, enumerable: false, configurable: false}

JSON.stringify가 더 이상 DOM 속성을 직렬화하지 않음

JSON.stringify는 프로토타입에 있는 DOM 속성을 직렬화하지 않습니다. 예를 들어 푸시 알림의 PushSubscription과 같은 객체를 직렬화하려는 경우 사이트에 영향을 미칠 수 있습니다.

Chrome 42 및 이전 버전에서는 다음과 같이 작동했을 것입니다.

> JSON.stringify(subscription);

{
    "endpoint": "https://something",
    "subscriptionId": "SomeID"
}

Chrome 43 이상에서는 프로토타입에 정의된 속성을 직렬화하지 않으므로 빈 객체가 반환됩니다.

> JSON.stringify(subscription);

{}

자체 직렬화 메서드를 제공해야 합니다. 예를 들어 다음과 같은 작업을 할 수 있습니다.

function stringifyDOMObject(object)
{
    function deepCopy(src) {
        if (typeof src != "object")
            return src;
        var dst = Array.isArray(src) ? [] : {};
        for (var property in src) {
            dst[property] = deepCopy(src[property]);
        }
        return dst;
    }
    return JSON.stringify(deepCopy(object));
}
var s = stringifyDOMObject(domObject);

엄격 모드에서 읽기 전용 속성에 쓰기를 수행하면 오류가 발생함

엄격 모드를 사용하는 경우 읽기 전용 속성에 쓰기 작업을 수행하면 예외가 발생합니다. 예를 들어 다음을 살펴보겠습니다.

function foo() {
    "use strict";
    var d = document.createElement("div");
    console.log(d.isContentEditable);
    d.isContentEditable = 1;
    console.log(d.isContentEditable);
}

Chrome 42 이하에서는 isContentEditable가 변경되지 않았지만 이 함수는 함수 실행 시 계속 실행되고 자동으로 전달되었습니다.

// Chrome 42 and earlier behavior
> foo();

false // isContentEditable
false // isContentEditable (after writing to read-only property)

이제 Chrome 43 이상에서는 예외가 발생합니다.

// Chrome 43 and onwards behavior
> foo();

false
Uncaught TypeError: Cannot set property isContentEditable of #<HTMLElement> which has only a getter

문제가 있습니다. 어떻게 해야 하나요?

안내를 따르거나 아래에 댓글을 남겨 대화를 나눠 보세요.

문제가 있는 사이트를 발견했습니다. 어떻게 해야 하나요?

좋은 질문이에요. 사이트 관련 문제는 대부분 사이트에서 getOwnProperty 메서드로 속성 인기척 감지를 실행하도록 선택했다는 사실에 기반합니다. 이 작업은 주로 사이트 소유자가 이전 WebKit 브라우저만 타겟팅한 경우에 발생합니다. 개발자는 다음과 같은 작업을 할 수 있습니다.

  • (Chrome) Issue Tracker에서 영향을 받은 사이트에 관한 문제를 신고합니다.
  • WebKit 레이더에 문제를 신고하고 https://bugs.webkit.org/show_bug.cgi?id=49739를 참조하세요.

일반적으로 이 변경사항을 따르는 데 관심이 있음